home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / mamesrc / src / mame / common.c next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  67.0 KB  |  2,747 lines

  1. /*********************************************************************
  2.  
  3.   common.c
  4.  
  5.   Generic functions, mostly ROM and graphics related.
  6.  
  7. *********************************************************************/
  8.  
  9. #include "driver.h"
  10.  
  11. /* These globals are only kept on a machine basis - LBO 042898 */
  12. unsigned int dispensed_tickets;
  13. unsigned int coins[COIN_COUNTERS];
  14. unsigned int lastcoin[COIN_COUNTERS];
  15. unsigned int coinlockedout[COIN_COUNTERS];
  16.  
  17. /* LBO */
  18. #ifdef LSB_FIRST
  19. #define intelLong(x) (x)
  20. #define BL0 0
  21. #define BL1 1
  22. #define BL2 2
  23. #define BL3 3
  24. #define WL0 0
  25. #define WL1 1
  26. #else
  27. #define intelLong(x) (((x << 24) | (((unsigned long) x) >> 24) | (( x & 0x0000ff00) << 8) | (( x & 0x00ff0000) >> 8)))
  28. #define BL0 3
  29. #define BL1 2
  30. #define BL2 1
  31. #define BL3 0
  32. #define WL0 1
  33. #define WL1 0
  34. #endif
  35.  
  36. #define TA
  37.  
  38. #ifdef ALIGN_INTS /* GSL 980108 read/write nonaligned dword routine for ARM processor etc */
  39.  
  40. INLINE int read_dword(void *address)
  41. {
  42.     if ((long)address & 3)
  43.     {
  44. #ifdef LSB_FIRST  /* little endian version */
  45.           return ( *((unsigned char *)address) +
  46.                 (*((unsigned char *)address+1) << 8)  +
  47.                 (*((unsigned char *)address+2) << 16) +
  48.                 (*((unsigned char *)address+3) << 24) );
  49. #else             /* big endian version */
  50.           return ( *((unsigned char *)address+3) +
  51.                 (*((unsigned char *)address+2) << 8)  +
  52.                 (*((unsigned char *)address+1) << 16) +
  53.                 (*((unsigned char *)address)   << 24) );
  54. #endif
  55.     }
  56.     else
  57.         return *(int *)address;
  58. }
  59.  
  60.  
  61. INLINE void write_dword(void *address, int data)
  62. {
  63.       if ((long)address & 3)
  64.     {
  65. #ifdef LSB_FIRST
  66.             *((unsigned char *)address) =    data;
  67.             *((unsigned char *)address+1) = (data >> 8);
  68.             *((unsigned char *)address+2) = (data >> 16);
  69.             *((unsigned char *)address+3) = (data >> 24);
  70. #else
  71.             *((unsigned char *)address+3) =  data;
  72.             *((unsigned char *)address+2) = (data >> 8);
  73.             *((unsigned char *)address+1) = (data >> 16);
  74.             *((unsigned char *)address)   = (data >> 24);
  75. #endif
  76.         return;
  77.       }
  78.       else
  79.         *(int *)address = data;
  80. }
  81. #else
  82. #define read_dword(address) *(int *)address
  83. #define write_dword(address,data) *(int *)address=data
  84. #endif
  85.  
  86.  
  87.  
  88. void showdisclaimer(void)   /* MAURY_BEGIN: dichiarazione */
  89. {
  90.     printf("MAME is an emulator: it reproduces, more or less faithfully, the behaviour of\n"
  91.          "several arcade machines. But hardware is useless without software, so an image\n"
  92.          "of the ROMs which run on that hardware is required. Such ROMs, like any other\n"
  93.          "commercial software, are copyrighted material and it is therefore illegal to\n"
  94.          "use them if you don't own the original arcade machine. Needless to say, ROMs\n"
  95.          "are not distributed together with MAME. Distribution of MAME together with ROM\n"
  96.          "images is a violation of copyright law and should be promptly reported to the\n"
  97.          "authors so that appropriate legal action can be taken.\n\n");
  98. }                           /* MAURY_END: dichiarazione */
  99.  
  100.  
  101. /***************************************************************************
  102.  
  103.   Read ROMs into memory.
  104.  
  105.   Arguments:
  106.   const struct RomModule *romp - pointer to an array of Rommodule structures,
  107.                                  as defined in common.h.
  108.  
  109. ***************************************************************************/
  110.  
  111. #ifdef MESS
  112. #define ROM_FILETYPE    OSD_FILETYPE_IMAGE /* The IMAGE type requires different handling */
  113. #else
  114. #define ROM_FILETYPE    OSD_FILETYPE_ROM
  115. #endif
  116.  
  117. int readroms(void)
  118. {
  119.     int region;
  120.     const struct RomModule *romp;
  121.     int checksumwarning = 0;
  122.     int lengthwarning = 0;
  123.     int total_roms,current_rom;
  124.     char buf[2048] = "";
  125.  
  126.  
  127.     total_roms = current_rom = 0;
  128.     romp = Machine->gamedrv->rom;
  129.     while (romp->name || romp->offset || romp->length)
  130.     {
  131.         if (romp->name && romp->name != (char *)-1)
  132.             total_roms++;
  133.  
  134.         romp++;
  135.     }
  136.  
  137.  
  138.     romp = Machine->gamedrv->rom;
  139.  
  140.     for (region = 0;region < MAX_MEMORY_REGIONS;region++)
  141.         Machine->memory_region[region] = 0;
  142.  
  143.     region = 0;
  144.  
  145.     while (romp->name || romp->offset || romp->length)
  146.     {
  147.         unsigned int region_size;
  148.         const char *name;
  149.  
  150.         /* Mish:  An 'optional' rom region, only loaded if sound emulation is turned on */
  151.         if (Machine->sample_rate==0 && (romp->offset & ROMFLAG_IGNORE)) {
  152.             if (errorlog) fprintf(errorlog,"readroms():  Ignoring rom region %d\n",region);
  153.             region++;
  154.  
  155.             romp++;
  156.             while (romp->name || romp->length)
  157.                 romp++;
  158.  
  159.             continue;
  160.         }
  161.  
  162.         if (romp->name || romp->length)
  163.         {
  164.             printf("Error in RomModule definition: expecting ROM_REGION\n");
  165.             goto getout;
  166.         }
  167.  
  168.         region_size = romp->offset & ~ROMFLAG_MASK;
  169.         if ((Machine->memory_region[region] = malloc(region_size)) == 0)
  170.         {
  171.             printf("readroms():  Unable to allocate %d bytes of RAM\n",region_size);
  172.             goto getout;
  173.         }
  174.         Machine->memory_region_length[region] = region_size;
  175.  
  176.         /* some games (i.e. Pleiades) want the memory clear on startup */
  177.         if (region_size < 0x100000)    /* don't clear large regions which will be filled anyway */
  178.             memset(Machine->memory_region[region],0,region_size);
  179.  
  180.         romp++;
  181.  
  182.         while (romp->length)
  183.         {
  184.             void *f;
  185.             int expchecksum = romp->crc;
  186.             int    explength = 0;
  187.  
  188.  
  189.             if (romp->name == 0)
  190.             {
  191.                 printf("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n");
  192.                 goto getout;
  193.             }
  194.             else if (romp->name == (char *)-1)
  195.             {
  196.                 printf("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n");
  197.                 goto getout;
  198.             }
  199.  
  200.             name = romp->name;
  201.  
  202.             /* update status display */
  203.             if (osd_display_loading_rom_message(name,++current_rom,total_roms) != 0)
  204.                goto getout;
  205.  
  206.             f = osd_fopen(Machine->gamedrv->name,name,ROM_FILETYPE,0);
  207.             if (f == 0 && Machine->gamedrv->clone_of)
  208.             {
  209.                 /* if the game is a clone, try loading the ROM from the main version */
  210.                 f = osd_fopen(Machine->gamedrv->clone_of->name,name,ROM_FILETYPE,0);
  211.  
  212.                 if (f == 0 && Machine->gamedrv->clone_of->clone_of)
  213.                 {
  214.                     /* clone of a clone (for NeoGeo clones) */
  215.                     f = osd_fopen(Machine->gamedrv->clone_of->clone_of->name,name,ROM_FILETYPE,0);
  216.                 }
  217.             }
  218.             if (f == 0)
  219.             {
  220.                 /* NS981003: support for "load by CRC" */
  221.                 char crc[9];
  222.  
  223.                 sprintf(crc,"%08x",romp->crc);
  224.                 f = osd_fopen(Machine->gamedrv->name,crc,ROM_FILETYPE,0);
  225.                 if (f == 0 && Machine->gamedrv->clone_of)
  226.                 {
  227.                     /* if the game is a clone, try loading the ROM from the main version */
  228.                     f = osd_fopen(Machine->gamedrv->clone_of->name,crc,ROM_FILETYPE,0);
  229.  
  230.                     if (f == 0 && Machine->gamedrv->clone_of->clone_of)
  231.                     {
  232.                         /* clone of a clone (for NeoGeo clones) */
  233.                         f = osd_fopen(Machine->gamedrv->clone_of->clone_of->name,crc,ROM_FILETYPE,0);
  234.                     }
  235.                 }
  236.             }
  237.  
  238.             if (f)
  239.             {
  240.                 do
  241.                 {
  242.                     unsigned char *c;
  243.                     unsigned int i;
  244.                     int length = romp->length & ~ROMFLAG_MASK;
  245.  
  246.  
  247.                     if (romp->name == (char *)-1)
  248.                         osd_fseek(f,0,SEEK_SET);    /* ROM_RELOAD */
  249.                     else
  250.                         explength += length;
  251.  
  252.                     if (romp->offset + length > region_size)
  253.                     {
  254.                         printf("Error in RomModule definition: %s out of memory region space\n",name);
  255.                         osd_fclose(f);
  256.                         goto getout;
  257.                     }
  258.  
  259.                     if (romp->length & ROMFLAG_ALTERNATE)
  260.                     {
  261.                         /* ROM_LOAD_EVEN and ROM_LOAD_ODD */
  262.                         /* copy the ROM data */
  263.                     #ifdef LSB_FIRST
  264.                         c = Machine->memory_region[region] + (romp->offset ^ 1);
  265.                     #else
  266.                         c = Machine->memory_region[region] + romp->offset;
  267.                     #endif
  268.  
  269.                         if (osd_fread_scatter(f,c,length,2) != length)
  270.                         {
  271.                             printf("Unable to read ROM %s\n",name);
  272.                             osd_fclose(f);
  273.                             goto printromlist;
  274.                         }
  275.                     }
  276.                     else if (romp->length & ROMFLAG_NIBBLE)
  277.                     {
  278.                         unsigned char *temp;
  279.  
  280.  
  281.                         temp = malloc (length);
  282.  
  283.                         if (!temp)
  284.                         {
  285.                             printf("Out of memory reading ROM %s\n",name);
  286.                             osd_fclose(f);
  287.                             goto getout;
  288.                         }
  289.  
  290.                         if (osd_fread(f,temp,length) != length)
  291.                         {
  292.                             printf("Unable to read ROM %s\n",name);
  293.                             free(temp);
  294.                             osd_fclose(f);
  295.                             goto printromlist;
  296.                         }
  297.  
  298.                         /* ROM_LOAD_NIB_LOW and ROM_LOAD_NIB_HIGH */
  299.                         c = Machine->memory_region[region] + romp->offset;
  300.                         if (romp->length & ROMFLAG_ALTERNATE)
  301.                         {
  302.                             /* Load into the high nibble */
  303.                             for (i = 0;i < length;i ++)
  304.                             {
  305.                                 c[i] = (c[i] & 0x0f) | ((temp[i] & 0x0f) << 4);
  306.                             }
  307.                         }
  308.                         else
  309.                         {
  310.                             /* Load into the low nibble */
  311.                             for (i = 0;i < length;i ++)
  312.                             {
  313.                                 c[i] = (c[i] & 0xf0) | (temp[i] & 0x0f);
  314.                             }
  315.                         }
  316.  
  317.                         free (temp);
  318.                     }
  319.                     else
  320.                     {
  321.                         int wide = romp->length & ROMFLAG_WIDE;
  322.                     #ifdef LSB_FIRST
  323.                         int swap = (romp->length & ROMFLAG_SWAP) ^ ROMFLAG_SWAP;
  324.                     #else
  325.                         int swap = romp->length & ROMFLAG_SWAP;
  326.                     #endif
  327.  
  328.                         osd_fread(f,Machine->memory_region[region] + romp->offset,length);
  329.  
  330.                         /* apply swappage */
  331.                         c = Machine->memory_region[region] + romp->offset;
  332.                         if (wide && swap)
  333.                         {
  334.                             for (i = 0; i < length; i += 2)
  335.                             {
  336.                                 int temp = c[i];
  337.                                 c[i] = c[i+1];
  338.                                 c[i+1] = temp;
  339.                             }
  340.                         }
  341.                     }
  342.  
  343.                     romp++;
  344.                 } while (romp->length && (romp->name == 0 || romp->name == (char *)-1));
  345.  
  346.                 if (explength != osd_fsize (f))
  347.                 {
  348.                     sprintf (&buf[strlen(buf)], "%-12s WRONG LENGTH (expected: %08x found: %08x)\n",
  349.                             name,explength,osd_fsize(f));
  350.                     lengthwarning++;
  351.                 }
  352.  
  353.                 if (expchecksum != osd_fcrc (f))
  354.                 {
  355.                     checksumwarning++;
  356.                     if (expchecksum)
  357.                         sprintf(&buf[strlen(buf)], "%-12s WRONG CRC (expected: %08x found: %08x)\n",
  358.                                 name,expchecksum,osd_fcrc(f));
  359.                     else
  360.                         sprintf(&buf[strlen(buf)],"%-12s NO GOOD DUMP KNOWN\n",name);
  361.                 }
  362.  
  363.                 osd_fclose(f);
  364.             }
  365.             else
  366.             {
  367.                 /* allow for a NO GOOD DUMP KNOWN rom to be missing */
  368.                 if (expchecksum == 0)
  369.                 {
  370.                     sprintf (&buf[strlen(buf)], "%-12s NOT FOUND (NO GOOD DUMP KNOWN)\n",
  371.                             name);
  372.                     lengthwarning++;
  373.  
  374.                     do
  375.                     {
  376.                         int i;
  377.  
  378.                         /* fill space with random data */
  379.                         for (i = 0;i < (romp->length & ~ROMFLAG_MASK);i++)
  380.                             Machine->memory_region[region][romp->offset + i] = rand();
  381.                         romp++;
  382.                     } while (romp->length && (romp->name == 0 || romp->name == (char *)-1));
  383.                 }
  384.                 else
  385.                 {
  386.                     if (options.gui_host)
  387.                         printf("Unable to open ROM %s. Your ROM set is incomplete or corrupt.\n", name);
  388.                     else
  389.                         fprintf(stderr, "Unable to open ROM %s\n",name);
  390.                     goto printromlist;
  391.                 }
  392.             }
  393.         }
  394.  
  395.         region++;
  396.     }
  397.  
  398.     /* final status display */
  399.     osd_display_loading_rom_message(0,current_rom,total_roms);
  400.  
  401.     if ((checksumwarning > 0) || (lengthwarning > 0))
  402.     {
  403.         strcat (buf, "WARNING: the game might not run correctly.\n");
  404.         printf ("%s", buf);
  405.  
  406.         if (!options.gui_host)
  407.         {
  408.             printf ("Press return to continue\n");
  409.             getchar();
  410.         }
  411.     }
  412.  
  413.     return 0;
  414.  
  415.  
  416. printromlist:
  417.  
  418.     /* final status display */
  419.     osd_display_loading_rom_message(0,current_rom,total_roms);
  420.  
  421.     if (!options.gui_host)
  422.     {
  423.         printf("\n");
  424.         showdisclaimer();
  425.         printf("Press return to continue\n");
  426.         getchar();
  427.  
  428.         printromlist(Machine->gamedrv->rom,Machine->gamedrv->name);
  429.     }
  430.  
  431. getout:
  432.     /* final status display */
  433.     osd_display_loading_rom_message(0,current_rom,total_roms);
  434.  
  435.     for (region = 0;region < MAX_MEMORY_REGIONS;region++)
  436.     {
  437.         free(Machine->memory_region[region]);
  438.         Machine->memory_region[region] = 0;
  439.     }
  440.  
  441.     return 1;
  442. }
  443.  
  444.  
  445. void printromlist(const struct RomModule *romp,const char *basename)
  446. {
  447.     printf("This is the list of the ROMs required for driver \"%s\".\n"
  448.             "Name              Size       Checksum\n",basename);
  449.     while (romp->name || romp->offset || romp->length)
  450.     {
  451.         romp++;    /* skip memory region definition */
  452.  
  453.         while (romp->length)
  454.         {
  455.             const char *name;
  456.             int length,expchecksum;
  457.  
  458.  
  459.             name = romp->name;
  460.             expchecksum = romp->crc;
  461.  
  462.             length = 0;
  463.  
  464.             do
  465.             {
  466.                 /* ROM_RELOAD */
  467.                 if (romp->name == (char *)-1)
  468.                     length = 0;    /* restart */
  469.  
  470.                 length += romp->length & ~ROMFLAG_MASK;
  471.  
  472.                 romp++;
  473.             } while (romp->length && (romp->name == 0 || romp->name == (char *)-1));
  474.  
  475.             if (expchecksum)
  476.                 printf("%-12s  %7d bytes  %08x\n",name,length,expchecksum);
  477.             else
  478.                 printf("%-12s  %7d bytes  NO GOOD DUMP KNOWN\n",name,length);
  479.         }
  480.     }
  481. }
  482.  
  483.  
  484. /***************************************************************************
  485.  
  486.   Read samples into memory.
  487.   This function is different from readroms() because it doesn't fail if
  488.   it doesn't find a file: it will load as many samples as it can find.
  489.  
  490. ***************************************************************************/
  491. static struct GameSample *read_wav_sample(void *f)
  492. {
  493.     unsigned long offset = 0;
  494.     UINT32 length, rate, filesize, temp32;
  495.     UINT16 bits, temp16;
  496.     char buf[32];
  497.     struct GameSample *result;
  498.  
  499.     /* read the core header and make sure it's a WAVE file */
  500.     offset += osd_fread(f, buf, 4);
  501.     if (offset < 4)
  502.         return NULL;
  503.     if (memcmp(&buf[0], "RIFF", 4) != 0)
  504.         return NULL;
  505.  
  506.     /* get the total size */
  507.     offset += osd_fread(f, &filesize, 4);
  508.     if (offset < 8)
  509.         return NULL;
  510.     filesize = intelLong(filesize);
  511.  
  512.     /* read the RIFF file type and make sure it's a WAVE file */
  513.     offset += osd_fread(f, buf, 4);
  514.     if (offset < 12)
  515.         return NULL;
  516.     if (memcmp(&buf[0], "WAVE", 4) != 0)
  517.         return NULL;
  518.  
  519.     /* seek until we find a format tag */
  520.     while (1)
  521.     {
  522.         offset += osd_fread(f, buf, 4);
  523.         offset += osd_fread(f, &length, 4);
  524.         length = intelLong(length);
  525.         if (memcmp(&buf[0], "fmt ", 4) == 0)
  526.             break;
  527.  
  528.         /* seek to the next block */
  529.         osd_fseek(f, length, SEEK_CUR);
  530.         offset += length;
  531.         if (offset >= filesize)
  532.             return NULL;
  533.     }
  534.  
  535.     /* read the format -- make sure it is PCM */
  536.     offset += osd_fread_lsbfirst(f, &temp16, 2);
  537.     if (temp16 != 1)
  538.         return NULL;
  539.  
  540.     /* number of channels -- only mono is supported */
  541.     offset += osd_fread_lsbfirst(f, &temp16, 2);
  542.     if (temp16 != 1)
  543.         return NULL;
  544.  
  545.     /* sample rate */
  546.     offset += osd_fread(f, &rate, 4);
  547.     rate = intelLong(rate);
  548.  
  549.     /* bytes/second and block alignment are ignored */
  550.     offset += osd_fread(f, buf, 6);
  551.  
  552.     /* bits/sample */
  553.     offset += osd_fread_lsbfirst(f, &bits, 2);
  554.     if (bits != 8 && bits != 16)
  555.         return NULL;
  556.  
  557.     /* seek past any extra data */
  558.     osd_fseek(f, length - 16, SEEK_CUR);
  559.     offset += length - 16;
  560.  
  561.     /* seek until we find a data tag */
  562.     while (1)
  563.     {
  564.         offset += osd_fread(f, buf, 4);
  565.         offset += osd_fread(f, &length, 4);
  566.         length = intelLong(length);
  567.         if (memcmp(&buf[0], "data", 4) == 0)
  568.             break;
  569.  
  570.         /* seek to the next block */
  571.         osd_fseek(f, length, SEEK_CUR);
  572.         offset += length;
  573.         if (offset >= filesize)
  574.             return NULL;
  575.     }
  576.  
  577.     /* allocate the game sample */
  578.     result = malloc(sizeof(struct GameSample) + length);
  579.     if (result == NULL)
  580.         return NULL;
  581.  
  582.     /* fill in the sample data */
  583.     result->length = length;
  584.     result->volume = 100;
  585.     result->smpfreq = rate;
  586.     result->resolution = bits;
  587.  
  588.     /* read the data in */
  589.     if (bits == 8)
  590.     {
  591.         osd_fread(f, result->data, length);
  592.  
  593.         /* convert 8-bit data to signed samples */
  594.         for (temp32 = 0; temp32 < length; temp32++)
  595.             result->data[temp32] ^= 0x80;
  596.     }
  597.     else
  598.     {
  599.         /* 16-bit data is fine as-is */
  600.         osd_fread_lsbfirst(f, result->data, length);
  601.     }
  602.  
  603.     return result;
  604. }
  605.  
  606. #ifndef AMIGA
  607. struct GameSamples *readsamples(const char **samplenames,const char *basename)
  608. /* V.V - avoids samples duplication */
  609. /* if first samplename is *dir, looks for samples into "basename" first, then "dir" */
  610. {
  611.     int i;
  612.     struct GameSamples *samples;
  613.     int skipfirst = 0;
  614.  
  615.     /* if the user doesn't want to use samples, bail */
  616.     if (!options.use_samples) return 0;
  617.  
  618.     if (samplenames == 0 || samplenames[0] == 0) return 0;
  619.  
  620.     if (samplenames[0][0] == '*')
  621.         skipfirst = 1;
  622.  
  623.     i = 0;
  624.     while (samplenames[i+skipfirst] != 0) i++;
  625.  
  626.     if ((samples = malloc(sizeof(struct GameSamples) + (i-1)*sizeof(struct GameSample))) == 0)
  627.         return 0;
  628.  
  629.     samples->total = i;
  630.     for (i = 0;i < samples->total;i++)
  631.         samples->sample[i] = 0;
  632.  
  633.     for (i = 0;i < samples->total;i++)
  634.     {
  635.         void *f;
  636.  
  637.         if (samplenames[i+skipfirst][0])
  638.         {
  639.             if ((f = osd_fopen(basename,samplenames[i+skipfirst],OSD_FILETYPE_SAMPLE,0)) == 0)
  640.                 if (skipfirst)
  641.                     f = osd_fopen(samplenames[0]+1,samplenames[i+skipfirst],OSD_FILETYPE_SAMPLE,0);
  642.             if (f != 0)
  643.             {
  644.                 samples->sample[i] = read_wav_sample(f);
  645.                 osd_fclose(f);
  646.             }
  647.         }
  648.     }
  649.  
  650.     return samples;
  651. }
  652. #endif
  653.  
  654. void freesamples(struct GameSamples *samples)
  655. {
  656.     int i;
  657.  
  658.  
  659.     if (samples == 0) return;
  660.  
  661.     for (i = 0;i < samples->total;i++)
  662.         free(samples->sample[i]);
  663.  
  664.     free(samples);
  665. }
  666.  
  667.  
  668. /* LBO 042898 - added coin counters */
  669. void coin_counter_w (int offset, int data)
  670. {
  671.     if (offset >= COIN_COUNTERS) return;
  672.     /* Count it only if the data has changed from 0 to non-zero */
  673.     if (data && (lastcoin[offset] == 0))
  674.     {
  675.         coins[offset] ++;
  676.     }
  677.     lastcoin[offset] = data;
  678. }
  679.  
  680. void coin_lockout_w (int offset, int data)
  681. {
  682.     if (offset >= COIN_COUNTERS) return;
  683.  
  684.     coinlockedout[offset] = data;
  685. }
  686.  
  687. /* Locks out all the coin inputs */
  688. void coin_lockout_global_w (int offset, int data)
  689. {
  690.     int i;
  691.  
  692.     for (i = 0; i < COIN_COUNTERS; i++)
  693.     {
  694.         coin_lockout_w(i, data);
  695.     }
  696. }
  697.  
  698. /***************************************************************************
  699.  
  700.   Function to convert the information stored in the graphic roms into a
  701.   more usable format.
  702.  
  703.   Back in the early '80s, arcade machines didn't have the memory or the
  704.   speed to handle bitmaps like we do today. They used "character maps",
  705.   instead: they had one or more sets of characters (usually 8x8 pixels),
  706.   which would be placed on the screen in order to form a picture. This was
  707.   very fast: updating a character mapped display is, rougly speaking, 64
  708.   times faster than updating an equivalent bitmap display, since you only
  709.   modify groups of 8x8 pixels and not the single pixels. However, it was
  710.   also much less versatile than a bitmap screen, since with only 256
  711.   characters you had to do all of your graphics. To overcome this
  712.   limitation, some special hardware graphics were used: "sprites". A sprite
  713.   is essentially a bitmap, usually larger than a character, which can be
  714.   placed anywhere on the screen (not limited to character boundaries) by
  715.   just telling the hardware the coordinates. Moreover, sprites can be
  716.   flipped along the major axis just by setting the appropriate bit (some
  717.   machines can flip characters as well). This saves precious memory, since
  718.   you need only one copy of the image instead of four.
  719.  
  720.   What about colors? Well, the early machines had a limited palette (let's
  721.   say 16-32 colors) and each character or sprite could not use all of them
  722.   at the same time. Characters and sprites data would use a limited amount
  723.   of bits per pixel (typically 2, which allowed them to address only four
  724.   different colors). You then needed some way to tell to the hardware which,
  725.   among the available colors, were the four colors. This was done using a
  726.   "color attribute", which typically was an index for a lookup table.
  727.  
  728.   OK, after this brief and incomplete introduction, let's come to the
  729.   purpose of this section: how to interpret the data which is stored in
  730.   the graphic roms. Unfortunately, there is no easy answer: it depends on
  731.   the hardware. The easiest way to find how data is encoded, is to start by
  732.   making a bit by bit dump of the rom. You will usually be able to
  733.   immediately recognize some pattern: if you are lucky, you will see
  734.   letters and numbers right away, otherwise you will see something which
  735.   looks like letters and numbers, but with halves switched, dilated, or
  736.   something like that. You'll then have to find a way to put it all
  737.   together to obtain our standard one byte per pixel representation. Two
  738.   things to remember:
  739.   - keep in mind that every pixel has typically two (or more) bits
  740.     associated with it, and they are not necessarily near to each other.
  741.   - characters might be rotated 90 degrees. That's because many games used a
  742.     tube rotated 90 degrees. Think how your monitor would look like if you
  743.     put it on its side ;-)
  744.  
  745.   After you have successfully decoded the characters, you have to decode
  746.   the sprites. This is usually more difficult, because sprites are larger,
  747.   maybe have more colors, and are more difficult to recognize when they are
  748.   messed up, since they are pure graphics without letters and numbers.
  749.   However, with some work you'll hopefully be able to work them out as
  750.   well. As a rule of thumb, the sprites should be encoded in a way not too
  751.   dissimilar from the characters.
  752.  
  753. ***************************************************************************/
  754. static int readbit(const unsigned char *src,int bitnum)
  755. {
  756.     return (src[bitnum / 8] >> (7 - bitnum % 8)) & 1;
  757. }
  758.  
  759.  
  760. void decodechar(struct GfxElement *gfx,int num,const unsigned char *src,const struct GfxLayout *gl)
  761. {
  762.     int plane,x,y;
  763.     unsigned char *dp;
  764.  
  765.  
  766.  
  767.     for (plane = 0;plane < gl->planes;plane++)
  768.     {
  769.         int offs;
  770.  
  771.  
  772.         offs = num * gl->charincrement + gl->planeoffset[plane];
  773.  
  774.         for (y = 0;y < gfx->height;y++)
  775.         {
  776.             dp = gfx->gfxdata->line[num * gfx->height + y];
  777.  
  778.             for (x = 0;x < gfx->width;x++)
  779.             {
  780.                 int xoffs,yoffs;
  781.  
  782.  
  783.                 if (plane == 0) dp[x] = 0;
  784.                 else dp[x] <<= 1;
  785.  
  786.                 xoffs = x;
  787.                 yoffs = y;
  788.  
  789.                 if (Machine->orientation & ORIENTATION_FLIP_X)
  790.                     xoffs = gfx->width-1 - xoffs;
  791.  
  792.                 if (Machine->orientation & ORIENTATION_FLIP_Y)
  793.                     yoffs = gfx->height-1 - yoffs;
  794.  
  795.                 if (Machine->orientation & ORIENTATION_SWAP_XY)
  796.                 {
  797.                     int temp;
  798.  
  799.  
  800.                     temp = xoffs;
  801.                     xoffs = yoffs;
  802.                     yoffs = temp;
  803.                 }
  804.  
  805.                 dp[x] += readbit(src,offs + gl->yoffset[yoffs] + gl->xoffset[xoffs]);
  806.             }
  807.         }
  808.     }
  809.  
  810.  
  811.     if (gfx->pen_usage)
  812.     {
  813.         /* fill the pen_usage array with info on the used pens */
  814.         gfx->pen_usage[num] = 0;
  815.  
  816.         for (y = 0;y < gfx->height;y++)
  817.         {
  818.             dp = gfx->gfxdata->line[num * gfx->height + y];
  819.  
  820.             for (x = 0;x < gfx->width;x++)
  821.             {
  822.                 gfx->pen_usage[num] |= 1 << dp[x];
  823.             }
  824.         }
  825.     }
  826. }
  827.  
  828.  
  829. struct GfxElement *decodegfx(const unsigned char *src,const struct GfxLayout *gl)
  830. {
  831.     int c;
  832.     struct osd_bitmap *bm;
  833.     struct GfxElement *gfx;
  834.  
  835.  
  836.     if ((gfx = malloc(sizeof(struct GfxElement))) == 0)
  837.         return 0;
  838.     memset(gfx,0,sizeof(struct GfxElement));
  839.  
  840.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  841.     {
  842.         gfx->width = gl->height;
  843.         gfx->height = gl->width;
  844.  
  845.         if ((bm = osd_create_bitmap(gl->total * gfx->height,gfx->width)) == 0)
  846.         {
  847.             free(gfx);
  848.             return 0;
  849.         }
  850.     }
  851.     else
  852.     {
  853.         gfx->width = gl->width;
  854.         gfx->height = gl->height;
  855.  
  856.         if ((bm = osd_create_bitmap(gfx->width,gl->total * gfx->height)) == 0)
  857.         {
  858.             free(gfx);
  859.             return 0;
  860.         }
  861.     }
  862.  
  863.     gfx->total_elements = gl->total;
  864.     gfx->color_granularity = 1 << gl->planes;
  865.     gfx->gfxdata = bm;
  866.  
  867.     gfx->pen_usage = 0; /* need to make sure this is NULL if the next test fails) */
  868.     if (gfx->color_granularity <= 32)    /* can't handle more than 32 pens */
  869.         gfx->pen_usage = malloc(gfx->total_elements * sizeof(int));
  870.         /* no need to check for failure, the code can work without pen_usage */
  871.  
  872.     for (c = 0;c < gl->total;c++)
  873.         decodechar(gfx,c,src,gl);
  874.  
  875.     return gfx;
  876. }
  877.  
  878.  
  879. void freegfx(struct GfxElement *gfx)
  880. {
  881.     if (gfx)
  882.     {
  883.         free(gfx->pen_usage);
  884.         osd_free_bitmap(gfx->gfxdata);
  885.         free(gfx);
  886.     }
  887. }
  888.  
  889.  
  890. /***************************************************************************
  891.  
  892.   Draw graphic elements in the specified bitmap.
  893.  
  894.   transparency == TRANSPARENCY_NONE - no transparency.
  895.   transparency == TRANSPARENCY_PEN - bits whose _original_ value is == transparent_color
  896.                                      are transparent. This is the most common kind of
  897.                                      transparency.
  898.   transparency == TRANSPARENCY_PENS - as above, but transparent_color is a mask of
  899.                                        transparent pens.
  900.   transparency == TRANSPARENCY_COLOR - bits whose _remapped_ value is == Machine->pens[transparent_color]
  901.                                      are transparent. This is used by e.g. Pac Man.
  902.   transparency == TRANSPARENCY_THROUGH - if the _destination_ pixel is == transparent_color,
  903.                                      the source pixel is drawn over it. This is used by
  904.                                      e.g. Jr. Pac Man to draw the sprites when the background
  905.                                      has priority over them.
  906.  
  907. ***************************************************************************/
  908. /* ASG 971011 -- moved this into a "core" function */
  909. /* ASG 980209 -- changed to drawgfx_core8 */
  910. static void drawgfx_core8(struct osd_bitmap *dest,const struct GfxElement *gfx,
  911.         unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
  912.         const struct rectangle *clip,int transparency,int transparent_color,int dirty)
  913. {
  914.     int ox,oy,ex,ey,y,start,dy;
  915.     const unsigned char *sd;
  916.     unsigned char *bm,*bme;
  917.     int col;
  918.     int *sd4;
  919.     int trans4,col4;
  920.     struct rectangle myclip;
  921.  
  922.  
  923.     if (!gfx) return;
  924.  
  925.     code %= gfx->total_elements;
  926.     color %= gfx->total_colors;
  927.  
  928.     /* if necessary, remap the transparent color */
  929.     if (transparency == TRANSPARENCY_COLOR)
  930.         transparent_color = Machine->pens[transparent_color];
  931.  
  932.     if (gfx->pen_usage)
  933.     {
  934.         int transmask;
  935.  
  936.  
  937.         transmask = 0;
  938.  
  939.         if (transparency == TRANSPARENCY_PEN)
  940.         {
  941.             transmask = 1 << transparent_color;
  942.         }
  943.         else if (transparency == TRANSPARENCY_PENS)
  944.         {
  945.             transmask = transparent_color;
  946.         }
  947.         else if (transparency == TRANSPARENCY_COLOR && gfx->colortable)
  948.         {
  949.             int i;
  950.             const unsigned short *paldata;
  951.  
  952.  
  953.             paldata = &gfx->colortable[gfx->color_granularity * color];
  954.  
  955.             for (i = gfx->color_granularity - 1;i >= 0;i--)
  956.             {
  957.                 if (paldata[i] == transparent_color)
  958.                     transmask |= 1 << i;
  959.             }
  960.         }
  961.  
  962.         if ((gfx->pen_usage[code] & ~transmask) == 0)
  963.             /* character is totally transparent, no need to draw */
  964.             return;
  965.         else if ((gfx->pen_usage[code] & transmask) == 0 && transparency != TRANSPARENCY_THROUGH)
  966.             /* character is totally opaque, can disable transparency */
  967.             transparency = TRANSPARENCY_NONE;
  968.     }
  969.  
  970.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  971.     {
  972.         int temp;
  973.  
  974.         temp = sx;
  975.         sx = sy;
  976.         sy = temp;
  977.  
  978.         temp = flipx;
  979.         flipx = flipy;
  980.         flipy = temp;
  981.  
  982.         if (clip)
  983.         {
  984.             /* clip and myclip might be the same, so we need a temporary storage */
  985.             temp = clip->min_x;
  986.             myclip.min_x = clip->min_y;
  987.             myclip.min_y = temp;
  988.             temp = clip->max_x;
  989.             myclip.max_x = clip->max_y;
  990.             myclip.max_y = temp;
  991.             clip = &myclip;
  992.         }
  993.     }
  994.     if (Machine->orientation & ORIENTATION_FLIP_X)
  995.     {
  996.         sx = dest->width - gfx->width - sx;
  997.         if (clip)
  998.         {
  999.             int temp;
  1000.  
  1001.  
  1002.             /* clip and myclip might be the same, so we need a temporary storage */
  1003.             temp = clip->min_x;
  1004.             myclip.min_x = dest->width-1 - clip->max_x;
  1005.             myclip.max_x = dest->width-1 - temp;
  1006.             myclip.min_y = clip->min_y;
  1007.             myclip.max_y = clip->max_y;
  1008.             clip = &myclip;
  1009.         }
  1010.     }
  1011.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  1012.     {
  1013.         sy = dest->height - gfx->height - sy;
  1014.         if (clip)
  1015.         {
  1016.             int temp;
  1017.  
  1018.  
  1019.             myclip.min_x = clip->min_x;
  1020.             myclip.max_x = clip->max_x;
  1021.             /* clip and myclip might be the same, so we need a temporary storage */
  1022.             temp = clip->min_y;
  1023.             myclip.min_y = dest->height-1 - clip->max_y;
  1024.             myclip.max_y = dest->height-1 - temp;
  1025.             clip = &myclip;
  1026.         }
  1027.     }
  1028.  
  1029.  
  1030.     /* check bounds */
  1031.     ox = sx;
  1032.     oy = sy;
  1033.     ex = sx + gfx->width-1;
  1034.     if (sx < 0) sx = 0;
  1035.     if (clip && sx < clip->min_x) sx = clip->min_x;
  1036.     if (ex >= dest->width) ex = dest->width-1;
  1037.     if (clip && ex > clip->max_x) ex = clip->max_x;
  1038.     if (sx > ex) return;
  1039.     ey = sy + gfx->height-1;
  1040.     if (sy < 0) sy = 0;
  1041.     if (clip && sy < clip->min_y) sy = clip->min_y;
  1042.     if (ey >= dest->height) ey = dest->height-1;
  1043.     if (clip && ey > clip->max_y) ey = clip->max_y;
  1044.     if (sy > ey) return;
  1045.  
  1046.     if (dirty)
  1047.         osd_mark_dirty (sx,sy,ex,ey,0);    /* ASG 971011 */
  1048.  
  1049.     /* start = code * gfx->height; */
  1050.     if (flipy)    /* Y flop */
  1051.     {
  1052.         start = code * gfx->height + gfx->height-1 - (sy-oy);
  1053.         dy = -1;
  1054.     }
  1055.     else        /* normal */
  1056.     {
  1057.         start = code * gfx->height + (sy-oy);
  1058.         dy = 1;
  1059.     }
  1060.  
  1061.  
  1062.     if (gfx->colortable)    /* remap colors */
  1063.     {
  1064.         const unsigned short *paldata;    /* ASG 980209 */
  1065.  
  1066.         paldata = &gfx->colortable[gfx->color_granularity * color];
  1067.  
  1068.         switch (transparency)
  1069.         {
  1070.             case TRANSPARENCY_NONE:
  1071.                 if (flipx)    /* X flip */
  1072.                 {
  1073.                     for (y = sy;y <= ey;y++)
  1074.                     {
  1075.                         bm  = dest->line[y];
  1076.                         bme = bm + ex;
  1077.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1078.                         for( bm += sx ; bm <= bme-7 ; bm+=8 )
  1079.                         {
  1080.                             sd-=8;
  1081.                             bm[0] = paldata[sd[8]];
  1082.                             bm[1] = paldata[sd[7]];
  1083.                             bm[2] = paldata[sd[6]];
  1084.                             bm[3] = paldata[sd[5]];
  1085.                             bm[4] = paldata[sd[4]];
  1086.                             bm[5] = paldata[sd[3]];
  1087.                             bm[6] = paldata[sd[2]];
  1088.                             bm[7] = paldata[sd[1]];
  1089.                         }
  1090.                         for( ; bm <= bme ; bm++ )
  1091.                             *bm = paldata[*(sd--)];
  1092.                         start+=dy;
  1093.                     }
  1094.                 }
  1095.                 else        /* normal */
  1096.                 {
  1097.                     for (y = sy;y <= ey;y++)
  1098.                     {
  1099.                         bm  = dest->line[y];
  1100.                         bme = bm + ex;
  1101.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1102.                         for( bm += sx ; bm <= bme-7 ; bm+=8 )
  1103.                         {
  1104.                             bm[0] = paldata[sd[0]];
  1105.                             bm[1] = paldata[sd[1]];
  1106.                             bm[2] = paldata[sd[2]];
  1107.                             bm[3] = paldata[sd[3]];
  1108.                             bm[4] = paldata[sd[4]];
  1109.                             bm[5] = paldata[sd[5]];
  1110.                             bm[6] = paldata[sd[6]];
  1111.                             bm[7] = paldata[sd[7]];
  1112.                             sd+=8;
  1113.                         }
  1114.                         for( ; bm <= bme ; bm++ )
  1115.                             *bm = paldata[*(sd++)];
  1116.                         start+=dy;
  1117.                     }
  1118.                 }
  1119.                 break;
  1120.  
  1121.             case TRANSPARENCY_PEN:
  1122.                 trans4 = transparent_color * 0x01010101;
  1123.                 if (flipx)    /* X flip */
  1124.                 {
  1125.                     for (y = sy;y <= ey;y++)
  1126.                     {
  1127.                         bm  = dest->line[y];
  1128.                         bme = bm + ex;
  1129.                         sd4 = (int *)(gfx->gfxdata->line[start] + gfx->width -1 - (sx-ox) -3);
  1130.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1131.                         {
  1132.                             if ((col4=read_dword(sd4)) != trans4){
  1133.                                 col = (col4>>24)&0xff;
  1134.                                 if (col != transparent_color) bm[BL0] = paldata[col];
  1135.                                 col = (col4>>16)&0xff;
  1136.                                 if (col != transparent_color) bm[BL1] = paldata[col];
  1137.                                 col = (col4>>8)&0xff;
  1138.                                 if (col != transparent_color) bm[BL2] = paldata[col];
  1139.                                 col = col4&0xff;
  1140.                                 if (col != transparent_color) bm[BL3] = paldata[col];
  1141.                             }
  1142.                             sd4--;
  1143.                         }
  1144.                         sd = (unsigned char *)sd4+3;
  1145.                         for( ; bm <= bme ; bm++ )
  1146.                         {
  1147.                             col = *(sd--);
  1148.                             if (col != transparent_color) *bm = paldata[col];
  1149.                         }
  1150.                         start+=dy;
  1151.                     }
  1152.                 }
  1153.                 else        /* normal */
  1154.                 {
  1155.                     for (y = sy;y <= ey;y++)
  1156.                     {
  1157.                         bm  = dest->line[y];
  1158.                         bme = bm + ex;
  1159.                         sd4 = (int *)(gfx->gfxdata->line[start] + (sx-ox));
  1160.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1161.                         {
  1162.                             if ((col4=read_dword(sd4)) != trans4){
  1163.                                 col = col4&0xff;
  1164.                                 if (col != transparent_color) bm[BL0] = paldata[col];
  1165.                                 col = (col4>>8)&0xff;
  1166.                                 if (col != transparent_color) bm[BL1] = paldata[col];
  1167.                                 col = (col4>>16)&0xff;
  1168.                                 if (col != transparent_color) bm[BL2] = paldata[col];
  1169.                                 col = (col4>>24)&0xff;
  1170.                                 if (col != transparent_color) bm[BL3] = paldata[col];
  1171.                             }
  1172.                             sd4++;
  1173.                         }
  1174.                         sd = (unsigned char *)sd4;
  1175.                         for( ; bm <= bme ; bm++ )
  1176.                         {
  1177.                             col = *(sd++);
  1178.                             if (col != transparent_color) *bm = paldata[col];
  1179.                         }
  1180.                         start+=dy;
  1181.                     }
  1182.                 }
  1183.                 break;
  1184.  
  1185.             case TRANSPARENCY_PENS:
  1186. #define PEN_IS_OPAQUE ((1<<col)&transparent_color) == 0
  1187.  
  1188.                 if (flipx) /* X flip */
  1189.                 {
  1190.                     for (y = sy;y <= ey;y++)
  1191.                     {
  1192.                         bm  = dest->line[y];
  1193.                         bme = bm + ex;
  1194.                         sd4 = (int *)(gfx->gfxdata->line[start] + gfx->width -1 - (sx-ox) -3);
  1195.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1196.                         {
  1197.                             col4=read_dword(sd4);
  1198.                             col = (col4>>24)&0xff;
  1199.                             if (PEN_IS_OPAQUE) bm[BL0] = paldata[col];
  1200.                             col = (col4>>16)&0xff;
  1201.                             if (PEN_IS_OPAQUE) bm[BL1] = paldata[col];
  1202.                             col = (col4>>8)&0xff;
  1203.                             if (PEN_IS_OPAQUE) bm[BL2] = paldata[col];
  1204.                             col = col4&0xff;
  1205.                             if (PEN_IS_OPAQUE) bm[BL3] = paldata[col];
  1206.                             sd4--;
  1207.                         }
  1208.                         sd = (unsigned char *)sd4+3;
  1209.                         for( ; bm <= bme ; bm++ )
  1210.                         {
  1211.                             col = *(sd--);
  1212.                             if (PEN_IS_OPAQUE) *bm = paldata[col];
  1213.                         }
  1214.                         start+=dy;
  1215.                     }
  1216.                 }
  1217.                 else /* normal */
  1218.                 {
  1219.                     for (y = sy;y <= ey;y++)
  1220.                     {
  1221.                         bm  = dest->line[y];
  1222.                         bme = bm + ex;
  1223.                         sd4 = (int *)(gfx->gfxdata->line[start] + (sx-ox));
  1224.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1225.                         {
  1226.                             col4=read_dword(sd4);
  1227.                             col = col4&0xff;
  1228.                             if (PEN_IS_OPAQUE) bm[BL0] = paldata[col];
  1229.                             col = (col4>>8)&0xff;
  1230.                             if (PEN_IS_OPAQUE) bm[BL1] = paldata[col];
  1231.                             col = (col4>>16)&0xff;
  1232.                             if (PEN_IS_OPAQUE) bm[BL2] = paldata[col];
  1233.                             col = (col4>>24)&0xff;
  1234.                             if (PEN_IS_OPAQUE) bm[BL3] = paldata[col];
  1235.                             sd4++;
  1236.                         }
  1237.                         sd = (unsigned char *)sd4;
  1238.                         for( ; bm <= bme ; bm++ )
  1239.                         {
  1240.                             col = *(sd++);
  1241.                             if (PEN_IS_OPAQUE) *bm = paldata[col];
  1242.                         }
  1243.                         start+=dy;
  1244.                     }
  1245.                 }
  1246.                 break;
  1247.  
  1248.             case TRANSPARENCY_COLOR:
  1249.                 if (flipx)    /* X flip */
  1250.                 {
  1251.                     for (y = sy;y <= ey;y++)
  1252.                     {
  1253.                         bm  = dest->line[y];
  1254.                         bme = bm + ex;
  1255.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1256.                         for( bm += sx ; bm <= bme ; bm++ )
  1257.                         {
  1258.                             col = paldata[*(sd--)];
  1259.                             if (col != transparent_color) *bm = col;
  1260.                         }
  1261.                         start+=dy;
  1262.                     }
  1263.                 }
  1264.                 else        /* normal */
  1265.                 {
  1266.                     for (y = sy;y <= ey;y++)
  1267.                     {
  1268.                         bm  = dest->line[y];
  1269.                         bme = bm + ex;
  1270.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1271.                         for( bm += sx ; bm <= bme ; bm++ )
  1272.                         {
  1273.                             col = paldata[*(sd++)];
  1274.                             if (col != transparent_color) *bm = col;
  1275.                         }
  1276.                         start+=dy;
  1277.                     }
  1278.                 }
  1279.                 break;
  1280.  
  1281.             case TRANSPARENCY_THROUGH:
  1282.                 if (flipx)    /* X flip */
  1283.                 {
  1284.                     for (y = sy;y <= ey;y++)
  1285.                     {
  1286.                         bm  = dest->line[y];
  1287.                         bme = bm + ex;
  1288.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1289.                         for( bm += sx ; bm <= bme ; bm++ )
  1290.                         {
  1291.                             if (*bm == transparent_color)
  1292.                                 *bm = paldata[*sd];
  1293.                             sd--;
  1294.                         }
  1295.                         start+=dy;
  1296.                     }
  1297.                 }
  1298.                 else        /* normal */
  1299.                 {
  1300.                     for (y = sy;y <= ey;y++)
  1301.                     {
  1302.                         bm  = dest->line[y];
  1303.                         bme = bm + ex;
  1304.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1305.                         for( bm += sx ; bm <= bme ; bm++ )
  1306.                         {
  1307.                             if (*bm == transparent_color)
  1308.                                 *bm = paldata[*sd];
  1309.                             sd++;
  1310.                         }
  1311.                         start+=dy;
  1312.                     }
  1313.                 }
  1314.                 break;
  1315.         }
  1316.     }
  1317.     else
  1318.     {
  1319.         switch (transparency)
  1320.         {
  1321.             case TRANSPARENCY_NONE:        /* do a verbatim copy (faster) */
  1322.                 if (flipx)    /* X flip */
  1323.                 {
  1324.                     for (y = sy;y <= ey;y++)
  1325.                     {
  1326.                         bm  = dest->line[y];
  1327.                         bme = bm + ex;
  1328.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1329.                         for( bm += sx ; bm <= bme-7 ; bm+=8 )
  1330.                         {
  1331.                             sd-=8;
  1332.                             bm[0] = sd[8];
  1333.                             bm[1] = sd[7];
  1334.                             bm[2] = sd[6];
  1335.                             bm[3] = sd[5];
  1336.                             bm[4] = sd[4];
  1337.                             bm[5] = sd[3];
  1338.                             bm[6] = sd[2];
  1339.                             bm[7] = sd[1];
  1340.                         }
  1341.                         for( ; bm <= bme ; bm++ )
  1342.                             *bm = *(sd--);
  1343.                         start+=dy;
  1344.                     }
  1345.                 }
  1346.                 else        /* normal */
  1347.                 {
  1348.                     for (y = sy;y <= ey;y++)
  1349.                     {
  1350.                         bm = dest->line[y] + sx;
  1351.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1352.                         memcpy(bm,sd,ex-sx+1);
  1353.                         start+=dy;
  1354.                     }
  1355.                 }
  1356.                 break;
  1357.  
  1358.             case TRANSPARENCY_PEN:
  1359.             case TRANSPARENCY_COLOR:
  1360.                 trans4 = transparent_color * 0x01010101;
  1361.  
  1362.                 if (flipx)    /* X flip */
  1363.                 {
  1364.                     for (y = sy;y <= ey;y++)
  1365.                     {
  1366.                         bm  = dest->line[y];
  1367.                         bme = bm + ex;
  1368.                         sd4 = (int *)(gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox) - 3);
  1369.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1370.                         {
  1371.                             if( (col4=read_dword(sd4)) != trans4 )
  1372.                             {
  1373.                                 col = (col4>>24)&0xff;
  1374.                                 if (col != transparent_color) bm[BL0] = col;
  1375.                                 col = (col4>>16)&0xff;
  1376.                                 if (col != transparent_color) bm[BL1] = col;
  1377.                                 col = (col4>>8)&0xff;
  1378.                                 if (col != transparent_color) bm[BL2] = col;
  1379.                                 col = col4&0xff;
  1380.                                 if (col != transparent_color) bm[BL3] = col;
  1381.                             }
  1382.                             sd4--;
  1383.                         }
  1384.                         sd = (unsigned char *)sd4+3;
  1385.                         for( ; bm <= bme ; bm++ )
  1386.                         {
  1387.                             col = *(sd--);
  1388.                             if (col != transparent_color) *bm = col;
  1389.                         }
  1390.                         start+=dy;
  1391.                     }
  1392.                 }
  1393.                 else    /* normal */
  1394.                 {
  1395.                     int xod4;
  1396.  
  1397.                     for (y = sy;y <= ey;y++)
  1398.                     {
  1399.                         bm = dest->line[y];
  1400.                         bme = bm + ex;
  1401.                         sd4 = (int *)(gfx->gfxdata->line[start] + (sx-ox));
  1402.                         bm += sx;
  1403.                         while( bm <= bme-3 )
  1404.                         {
  1405.                             /* bypass loop */
  1406.                             while( bm <= bme-3 && read_dword(sd4) == trans4 )
  1407.                             { sd4++; bm+=4; }
  1408.                             /* drawing loop */
  1409.                             while( bm <= bme-3 && (col4=read_dword(sd4)) != trans4 )
  1410.                             {
  1411.                                 xod4 = col4^trans4;
  1412.                                 if( (xod4&0x000000ff) && (xod4&0x0000ff00) &&
  1413.                                     (xod4&0x00ff0000) && (xod4&0xff000000) )
  1414.                                 {
  1415.                                     write_dword((int *)bm,col4);
  1416.                                 }
  1417.                                 else
  1418.                                 {
  1419.                                     if(xod4&0x000000ff) bm[BL0] = col4;
  1420.                                     if(xod4&0x0000ff00) bm[BL1] = col4>>8;
  1421.                                     if(xod4&0x00ff0000) bm[BL2] = col4>>16;
  1422.                                     if(xod4&0xff000000) bm[BL3] = col4>>24;
  1423.                                 }
  1424.                                 sd4++;
  1425.                                 bm+=4;
  1426.                             }
  1427.                         }
  1428.                         sd = (unsigned char *)sd4;
  1429.                         for( ; bm <= bme ; bm++ )
  1430.                         {
  1431.                             col = *(sd++);
  1432.                             if (col != transparent_color) *bm = col;
  1433.                         }
  1434.                         start+=dy;
  1435.                     }
  1436.                 }
  1437.                 break;
  1438.  
  1439.             case TRANSPARENCY_THROUGH:
  1440.                 if (flipx)    /* X flip */
  1441.                 {
  1442.                     for (y = sy;y <= ey;y++)
  1443.                     {
  1444.                         bm = dest->line[y];
  1445.                         bme = bm + ex;
  1446.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1447.                         for( bm = bm+sx ; bm <= bme ; bm++ )
  1448.                         {
  1449.                             if (*bm == transparent_color)
  1450.                                 *bm = *sd;
  1451.                             sd--;
  1452.                         }
  1453.                         start+=dy;
  1454.                     }
  1455.                 }
  1456.                 else        /* normal */
  1457.                 {
  1458.                     for (y = sy;y <= ey;y++)
  1459.                     {
  1460.                         bm = dest->line[y];
  1461.                         bme = bm + ex;
  1462.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1463.                         for( bm = bm+sx ; bm <= bme ; bm++ )
  1464.                         {
  1465.                             if (*bm == transparent_color)
  1466.                                 *bm = *sd;
  1467.                             sd++;
  1468.                         }
  1469.                         start+=dy;
  1470.                     }
  1471.                 }
  1472.                 break;
  1473.         }
  1474.     }
  1475. }
  1476.  
  1477.  
  1478. static void drawgfx_core16(struct osd_bitmap *dest,const struct GfxElement *gfx,
  1479.         unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
  1480.         const struct rectangle *clip,int transparency,int transparent_color,int dirty)
  1481. {
  1482.     int ox,oy,ex,ey,y,start,dy;
  1483.     unsigned short *bm,*bme;
  1484.     int col;
  1485.     struct rectangle myclip;
  1486.  
  1487.  
  1488.     if (!gfx) return;
  1489.  
  1490.     code %= gfx->total_elements;
  1491.     color %= gfx->total_colors;
  1492.  
  1493.     /* if necessary, remap the transparent color */
  1494.     if (transparency == TRANSPARENCY_COLOR)
  1495.         transparent_color = Machine->pens[transparent_color];
  1496.  
  1497.     if (gfx->pen_usage)
  1498.     {
  1499.         int transmask;
  1500.  
  1501.  
  1502.         transmask = 0;
  1503.  
  1504.         if (transparency == TRANSPARENCY_PEN)
  1505.         {
  1506.             transmask = 1 << transparent_color;
  1507.         }
  1508.         else if (transparency == TRANSPARENCY_PENS)
  1509.         {
  1510.             transmask = transparent_color;
  1511.         }
  1512.         else if (transparency == TRANSPARENCY_COLOR && gfx->colortable)
  1513.         {
  1514.             int i;
  1515.             const unsigned short *paldata;
  1516.  
  1517.  
  1518.             paldata = &gfx->colortable[gfx->color_granularity * color];
  1519.  
  1520.             for (i = gfx->color_granularity - 1;i >= 0;i--)
  1521.             {
  1522.                 if (paldata[i] == transparent_color)
  1523.                     transmask |= 1 << i;
  1524.             }
  1525.         }
  1526.  
  1527.         if ((gfx->pen_usage[code] & ~transmask) == 0)
  1528.             /* character is totally transparent, no need to draw */
  1529.             return;
  1530.         else if ((gfx->pen_usage[code] & transmask) == 0 && transparency != TRANSPARENCY_THROUGH)
  1531.             /* character is totally opaque, can disable transparency */
  1532.             transparency = TRANSPARENCY_NONE;
  1533.     }
  1534.  
  1535.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  1536.     {
  1537.         int temp;
  1538.  
  1539.         temp = sx;
  1540.         sx = sy;
  1541.         sy = temp;
  1542.  
  1543.         temp = flipx;
  1544.         flipx = flipy;
  1545.         flipy = temp;
  1546.  
  1547.         if (clip)
  1548.         {
  1549.             /* clip and myclip might be the same, so we need a temporary storage */
  1550.             temp = clip->min_x;
  1551.             myclip.min_x = clip->min_y;
  1552.             myclip.min_y = temp;
  1553.             temp = clip->max_x;
  1554.             myclip.max_x = clip->max_y;
  1555.             myclip.max_y = temp;
  1556.             clip = &myclip;
  1557.         }
  1558.     }
  1559.     if (Machine->orientation & ORIENTATION_FLIP_X)
  1560.     {
  1561.         sx = dest->width - gfx->width - sx;
  1562.         if (clip)
  1563.         {
  1564.             int temp;
  1565.  
  1566.  
  1567.             /* clip and myclip might be the same, so we need a temporary storage */
  1568.             temp = clip->min_x;
  1569.             myclip.min_x = dest->width-1 - clip->max_x;
  1570.             myclip.max_x = dest->width-1 - temp;
  1571.             myclip.min_y = clip->min_y;
  1572.             myclip.max_y = clip->max_y;
  1573.             clip = &myclip;
  1574.         }
  1575.     }
  1576.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  1577.     {
  1578.         sy = dest->height - gfx->height - sy;
  1579.         if (clip)
  1580.         {
  1581.             int temp;
  1582.  
  1583.  
  1584.             myclip.min_x = clip->min_x;
  1585.             myclip.max_x = clip->max_x;
  1586.             /* clip and myclip might be the same, so we need a temporary storage */
  1587.             temp = clip->min_y;
  1588.             myclip.min_y = dest->height-1 - clip->max_y;
  1589.             myclip.max_y = dest->height-1 - temp;
  1590.             clip = &myclip;
  1591.         }
  1592.     }
  1593.  
  1594.  
  1595.     /* check bounds */
  1596.     ox = sx;
  1597.     oy = sy;
  1598.     ex = sx + gfx->width-1;
  1599.     if (sx < 0) sx = 0;
  1600.     if (clip && sx < clip->min_x) sx = clip->min_x;
  1601.     if (ex >= dest->width) ex = dest->width-1;
  1602.     if (clip && ex > clip->max_x) ex = clip->max_x;
  1603.     if (sx > ex) return;
  1604.     ey = sy + gfx->height-1;
  1605.     if (sy < 0) sy = 0;
  1606.     if (clip && sy < clip->min_y) sy = clip->min_y;
  1607.     if (ey >= dest->height) ey = dest->height-1;
  1608.     if (clip && ey > clip->max_y) ey = clip->max_y;
  1609.     if (sy > ey) return;
  1610.  
  1611.     if (dirty)
  1612.         osd_mark_dirty (sx,sy,ex,ey,0);    /* ASG 971011 */
  1613.  
  1614.     /* start = code * gfx->height; */
  1615.     if (flipy)    /* Y flop */
  1616.     {
  1617.         start = code * gfx->height + gfx->height-1 - (sy-oy);
  1618.         dy = -1;
  1619.     }
  1620.     else        /* normal */
  1621.     {
  1622.         start = code * gfx->height + (sy-oy);
  1623.         dy = 1;
  1624.     }
  1625.  
  1626.  
  1627.     if (gfx->colortable)    /* remap colors -- assumes 8-bit source */
  1628.     {
  1629.         int *sd4;
  1630.         int trans4,col4;
  1631.         const unsigned char *sd;
  1632.         const unsigned short *paldata;
  1633.  
  1634.         paldata = &gfx->colortable[gfx->color_granularity * color];
  1635.  
  1636.         switch (transparency)
  1637.         {
  1638.             case TRANSPARENCY_NONE:
  1639.                 if (flipx)    /* X flip */
  1640.                 {
  1641.                     for (y = sy;y <= ey;y++)
  1642.                     {
  1643.                         bm  = (unsigned short *)dest->line[y];
  1644.                         bme = bm + ex;
  1645.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1646.                         for( bm += sx ; bm <= bme-7 ; bm+=8 )
  1647.                         {
  1648.                             sd-=8;
  1649.                             bm[0] = paldata[sd[8]];
  1650.                             bm[1] = paldata[sd[7]];
  1651.                             bm[2] = paldata[sd[6]];
  1652.                             bm[3] = paldata[sd[5]];
  1653.                             bm[4] = paldata[sd[4]];
  1654.                             bm[5] = paldata[sd[3]];
  1655.                             bm[6] = paldata[sd[2]];
  1656.                             bm[7] = paldata[sd[1]];
  1657.                         }
  1658.                         for( ; bm <= bme ; bm++ )
  1659.                             *bm = paldata[*(sd--)];
  1660.                         start+=dy;
  1661.                     }
  1662.                 }
  1663.                 else        /* normal */
  1664.                 {
  1665.                     for (y = sy;y <= ey;y++)
  1666.                     {
  1667.                         bm  = (unsigned short *)dest->line[y];
  1668.                         bme = bm + ex;
  1669.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1670.                         for( bm += sx ; bm <= bme-7 ; bm+=8 )
  1671.                         {
  1672.                             bm[0] = paldata[sd[0]];
  1673.                             bm[1] = paldata[sd[1]];
  1674.                             bm[2] = paldata[sd[2]];
  1675.                             bm[3] = paldata[sd[3]];
  1676.                             bm[4] = paldata[sd[4]];
  1677.                             bm[5] = paldata[sd[5]];
  1678.                             bm[6] = paldata[sd[6]];
  1679.                             bm[7] = paldata[sd[7]];
  1680.                             sd+=8;
  1681.                         }
  1682.                         for( ; bm <= bme ; bm++ )
  1683.                             *bm = paldata[*(sd++)];
  1684.                         start+=dy;
  1685.                     }
  1686.                 }
  1687.                 break;
  1688.  
  1689.             case TRANSPARENCY_PEN:
  1690.                 trans4 = transparent_color * 0x01010101;
  1691.                 if (flipx)    /* X flip */
  1692.                 {
  1693.                     for (y = sy;y <= ey;y++)
  1694.                     {
  1695.                         bm  = (unsigned short *)dest->line[y];
  1696.                         bme = bm + ex;
  1697.                         sd4 = (int *)(gfx->gfxdata->line[start] + gfx->width -1 - (sx-ox) -3);
  1698.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1699.                         {
  1700.                             if ((col4=read_dword(sd4)) != trans4){
  1701.                                 col = (col4>>24)&0xff;
  1702.                                 if (col != transparent_color) bm[BL0] = paldata[col];
  1703.                                 col = (col4>>16)&0xff;
  1704.                                 if (col != transparent_color) bm[BL1] = paldata[col];
  1705.                                 col = (col4>>8)&0xff;
  1706.                                 if (col != transparent_color) bm[BL2] = paldata[col];
  1707.                                 col = col4&0xff;
  1708.                                 if (col != transparent_color) bm[BL3] = paldata[col];
  1709.                             }
  1710.                             sd4--;
  1711.                         }
  1712.                         sd = (unsigned char *)sd4+3;
  1713.                         for( ; bm <= bme ; bm++ )
  1714.                         {
  1715.                             col = *(sd--);
  1716.                             if (col != transparent_color) *bm = paldata[col];
  1717.                         }
  1718.                         start+=dy;
  1719.                     }
  1720.                 }
  1721.                 else        /* normal */
  1722.                 {
  1723.                     for (y = sy;y <= ey;y++)
  1724.                     {
  1725.                         bm  = (unsigned short *)dest->line[y];
  1726.                         bme = bm + ex;
  1727.                         sd4 = (int *)(gfx->gfxdata->line[start] + (sx-ox));
  1728.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1729.                         {
  1730.                             if ((col4=read_dword(sd4)) != trans4){
  1731.                                 col = col4&0xff;
  1732.                                 if (col != transparent_color) bm[BL0] = paldata[col];
  1733.                                 col = (col4>>8)&0xff;
  1734.                                 if (col != transparent_color) bm[BL1] = paldata[col];
  1735.                                 col = (col4>>16)&0xff;
  1736.                                 if (col != transparent_color) bm[BL2] = paldata[col];
  1737.                                 col = (col4>>24)&0xff;
  1738.                                 if (col != transparent_color) bm[BL3] = paldata[col];
  1739.                             }
  1740.                             sd4++;
  1741.                         }
  1742.                         sd = (unsigned char *)sd4;
  1743.                         for( ; bm <= bme ; bm++ )
  1744.                         {
  1745.                             col = *(sd++);
  1746.                             if (col != transparent_color) *bm = paldata[col];
  1747.                         }
  1748.                         start+=dy;
  1749.                     }
  1750.                 }
  1751.                 break;
  1752.  
  1753.             case TRANSPARENCY_PENS:
  1754. #define PEN_IS_OPAQUE ((1<<col)&transparent_color) == 0
  1755.  
  1756.                 if (flipx) /* X flip */
  1757.                 {
  1758.                     for (y = sy;y <= ey;y++)
  1759.                     {
  1760.                         bm  = (unsigned short *)dest->line[y];
  1761.                         bme = bm + ex;
  1762.                         sd4 = (int *)(gfx->gfxdata->line[start] + gfx->width -1 - (sx-ox) -3);
  1763.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1764.                         {
  1765.                             col4=read_dword(sd4);
  1766.                             col = (col4>>24)&0xff;
  1767.                             if (PEN_IS_OPAQUE) bm[BL0] = paldata[col];
  1768.                             col = (col4>>16)&0xff;
  1769.                             if (PEN_IS_OPAQUE) bm[BL1] = paldata[col];
  1770.                             col = (col4>>8)&0xff;
  1771.                             if (PEN_IS_OPAQUE) bm[BL2] = paldata[col];
  1772.                             col = col4&0xff;
  1773.                             if (PEN_IS_OPAQUE) bm[BL3] = paldata[col];
  1774.                             sd4--;
  1775.                         }
  1776.                         sd = (unsigned char *)sd4+3;
  1777.                         for( ; bm <= bme ; bm++ )
  1778.                         {
  1779.                             col = *(sd--);
  1780.                             if (PEN_IS_OPAQUE) *bm = paldata[col];
  1781.                         }
  1782.                         start+=dy;
  1783.                     }
  1784.                 }
  1785.                 else /* normal */
  1786.                 {
  1787.                     for (y = sy;y <= ey;y++)
  1788.                     {
  1789.                         bm  = (unsigned short *)dest->line[y];
  1790.                         bme = bm + ex;
  1791.                         sd4 = (int *)(gfx->gfxdata->line[start] + (sx-ox));
  1792.                         for( bm += sx ; bm <= bme-3 ; bm+=4 )
  1793.                         {
  1794.                             col4=read_dword(sd4);
  1795.                             col = col4&0xff;
  1796.                             if (PEN_IS_OPAQUE) bm[BL0] = paldata[col];
  1797.                             col = (col4>>8)&0xff;
  1798.                             if (PEN_IS_OPAQUE) bm[BL1] = paldata[col];
  1799.                             col = (col4>>16)&0xff;
  1800.                             if (PEN_IS_OPAQUE) bm[BL2] = paldata[col];
  1801.                             col = (col4>>24)&0xff;
  1802.                             if (PEN_IS_OPAQUE) bm[BL3] = paldata[col];
  1803.                             sd4++;
  1804.                         }
  1805.                         sd = (unsigned char *)sd4;
  1806.                         for( ; bm <= bme ; bm++ )
  1807.                         {
  1808.                             col = *(sd++);
  1809.                             if (PEN_IS_OPAQUE) *bm = paldata[col];
  1810.                         }
  1811.                         start+=dy;
  1812.                     }
  1813.                 }
  1814.                 break;
  1815.  
  1816.             case TRANSPARENCY_COLOR:
  1817.                 if (flipx)    /* X flip */
  1818.                 {
  1819.                     for (y = sy;y <= ey;y++)
  1820.                     {
  1821.                         bm  = (unsigned short *)dest->line[y];
  1822.                         bme = bm + ex;
  1823.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1824.                         for( bm += sx ; bm <= bme ; bm++ )
  1825.                         {
  1826.                             col = paldata[*(sd--)];
  1827.                             if (col != transparent_color) *bm = col;
  1828.                         }
  1829.                         start+=dy;
  1830.                     }
  1831.                 }
  1832.                 else        /* normal */
  1833.                 {
  1834.                     for (y = sy;y <= ey;y++)
  1835.                     {
  1836.                         bm  = (unsigned short *)dest->line[y];
  1837.                         bme = bm + ex;
  1838.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1839.                         for( bm += sx ; bm <= bme ; bm++ )
  1840.                         {
  1841.                             col = paldata[*(sd++)];
  1842.                             if (col != transparent_color) *bm = col;
  1843.                         }
  1844.                         start+=dy;
  1845.                     }
  1846.                 }
  1847.                 break;
  1848.  
  1849.             case TRANSPARENCY_THROUGH:
  1850.                 if (flipx)    /* X flip */
  1851.                 {
  1852.                     for (y = sy;y <= ey;y++)
  1853.                     {
  1854.                         bm  = (unsigned short *)dest->line[y];
  1855.                         bme = bm + ex;
  1856.                         sd = gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1857.                         for( bm += sx ; bm <= bme ; bm++ )
  1858.                         {
  1859.                             if (*bm == transparent_color)
  1860.                                 *bm = paldata[*sd];
  1861.                             sd--;
  1862.                         }
  1863.                         start+=dy;
  1864.                     }
  1865.                 }
  1866.                 else        /* normal */
  1867.                 {
  1868.                     for (y = sy;y <= ey;y++)
  1869.                     {
  1870.                         bm  = (unsigned short *)dest->line[y];
  1871.                         bme = bm + ex;
  1872.                         sd = gfx->gfxdata->line[start] + (sx-ox);
  1873.                         for( bm += sx ; bm <= bme ; bm++ )
  1874.                         {
  1875.                             if (*bm == transparent_color)
  1876.                                 *bm = paldata[*sd];
  1877.                             sd++;
  1878.                         }
  1879.                         start+=dy;
  1880.                     }
  1881.                 }
  1882.                 break;
  1883.         }
  1884.     }
  1885.     else    /* not palette mapped -- assumes 16-bit to 16-bit */
  1886.     {
  1887.         int *sd2;
  1888.         int trans2,col2;
  1889.         const unsigned short *sd;
  1890.  
  1891.         switch (transparency)
  1892.         {
  1893.             case TRANSPARENCY_NONE:        /* do a verbatim copy (faster) */
  1894.                 if (flipx)    /* X flip */
  1895.                 {
  1896.                     for (y = sy;y <= ey;y++)
  1897.                     {
  1898.                         bm  = (unsigned short *)dest->line[y];
  1899.                         bme = bm + ex;
  1900.                         sd = (unsigned short *)gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  1901.                         for( bm += sx ; bm <= bme-7 ; bm+=8 )
  1902.                         {
  1903.                             sd-=8;
  1904.                             bm[0] = sd[8];
  1905.                             bm[1] = sd[7];
  1906.                             bm[2] = sd[6];
  1907.                             bm[3] = sd[5];
  1908.                             bm[4] = sd[4];
  1909.                             bm[5] = sd[3];
  1910.                             bm[6] = sd[2];
  1911.                             bm[7] = sd[1];
  1912.                         }
  1913.                         for( ; bm <= bme ; bm++ )
  1914.                             *bm = *(sd--);
  1915.                         start+=dy;
  1916.                     }
  1917.                 }
  1918.                 else        /* normal */
  1919.                 {
  1920.                     for (y = sy;y <= ey;y++)
  1921.                     {
  1922.                         bm = (unsigned short *)dest->line[y] + sx;
  1923.                         sd = (unsigned short *)gfx->gfxdata->line[start] + (sx-ox);
  1924.                         memcpy(bm,sd,(ex-sx+1)*2);
  1925.                         start+=dy;
  1926.                     }
  1927.                 }
  1928.                 break;
  1929.  
  1930.             case TRANSPARENCY_PEN:
  1931.             case TRANSPARENCY_COLOR:
  1932.                 trans2 = transparent_color * 0x00010001;
  1933.  
  1934.                 if (flipx)    /* X flip */
  1935.                 {
  1936.                     for (y = sy;y <= ey;y++)
  1937.                     {
  1938.                         bm  = (unsigned short *)dest->line[y];
  1939.                         bme = bm + ex;
  1940.                         sd2 = (int *)((unsigned short *)gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox) - 3);
  1941.                         for( bm += sx ; bm <= bme-1 ; bm+=2 )
  1942.                         {
  1943.                             if( (col2=read_dword(sd2)) != trans2 )
  1944.                             {
  1945.                                 col = (col2>>16)&0xffff;
  1946.                                 if (col != transparent_color) bm[WL0] = col;
  1947.                                 col = col2&0xffff;
  1948.                                 if (col != transparent_color) bm[WL1] = col;
  1949.                             }
  1950.                             sd2--;
  1951.                         }
  1952.                         sd = (unsigned short *)sd2+1;
  1953.                         for( ; bm <= bme ; bm++ )
  1954.                         {
  1955.                             col = *(sd--);
  1956.                             if (col != transparent_color) *bm = col;
  1957.                         }
  1958.                         start+=dy;
  1959.                     }
  1960.                 }
  1961.                 else    /* normal */
  1962.                 {
  1963.                     int xod2;
  1964.  
  1965.                     for (y = sy;y <= ey;y++)
  1966.                     {
  1967.                         bm = (unsigned short *)dest->line[y];
  1968.                         bme = bm + ex;
  1969.                         sd2 = (int *)((unsigned short *)gfx->gfxdata->line[start] + (sx-ox));
  1970.                         bm += sx;
  1971.                         while( bm <= bme-1 )
  1972.                         {
  1973.                             /* bypass loop */
  1974.                             while( bm <= bme-1 && read_dword(sd2) == trans2 )
  1975.                             { sd2++; bm+=2; }
  1976.                             /* drawing loop */
  1977.                             while( bm <= bme-1 && (col2=read_dword(sd2)) != trans2 )
  1978.                             {
  1979.                                 xod2 = col2^trans2;
  1980.                                 if( (xod2&0x0000ffff) && (xod2&0xffff0000) )
  1981.                                 {
  1982.                                     write_dword((int *)bm, col2);
  1983.                                 }
  1984.                                 else
  1985.                                 {
  1986.                                     if(xod2&0x0000ffff) bm[WL0] = col2;
  1987.                                     if(xod2&0xffff0000) bm[WL1] = col2>>16;
  1988.                                 }
  1989.                                 sd2++;
  1990.                                 bm+=2;
  1991.                             }
  1992.                         }
  1993.                         sd = (unsigned short *)sd2;
  1994.                         for( ; bm <= bme ; bm++ )
  1995.                         {
  1996.                             col = *(sd++);
  1997.                             if (col != transparent_color) *bm = col;
  1998.                         }
  1999.                         start+=dy;
  2000.                     }
  2001.                 }
  2002.                 break;
  2003.  
  2004.             case TRANSPARENCY_THROUGH:
  2005.                 if (flipx)    /* X flip */
  2006.                 {
  2007.                     for (y = sy;y <= ey;y++)
  2008.                     {
  2009.                         bm = (unsigned short *)dest->line[y];
  2010.                         bme = bm + ex;
  2011.                         sd = (unsigned short *)gfx->gfxdata->line[start] + gfx->width-1 - (sx-ox);
  2012.                         for( bm = bm+sx ; bm <= bme ; bm++ )
  2013.                         {
  2014.                             if (*bm == transparent_color)
  2015.                                 *bm = *sd;
  2016.                             sd--;
  2017.                         }
  2018.                         start+=dy;
  2019.                     }
  2020.                 }
  2021.                 else        /* normal */
  2022.                 {
  2023.                     for (y = sy;y <= ey;y++)
  2024.                     {
  2025.                         bm = (unsigned short *)dest->line[y];
  2026.                         bme = bm + ex;
  2027.                         sd = (unsigned short *)gfx->gfxdata->line[start] + (sx-ox);
  2028.                         for( bm = bm+sx ; bm <= bme ; bm++ )
  2029.                         {
  2030.                             if (*bm == transparent_color)
  2031.                                 *bm = *sd;
  2032.                             sd++;
  2033.                         }
  2034.                         start+=dy;
  2035.                     }
  2036.                 }
  2037.                 break;
  2038.         }
  2039.     }
  2040. }
  2041.  
  2042.  
  2043. /* ASG 971011 - this is the real draw gfx now */
  2044. void drawgfx(struct osd_bitmap *dest,const struct GfxElement *gfx,
  2045.         unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
  2046.         const struct rectangle *clip,int transparency,int transparent_color)
  2047. {
  2048.     /* ASG 980209 -- separate 8-bit from 16-bit here */
  2049.     if (dest->depth != 16)
  2050.         drawgfx_core8(dest,gfx,code,color,flipx,flipy,sx,sy,clip,transparency,transparent_color,1);
  2051.     else
  2052.         drawgfx_core16(dest,gfx,code,color,flipx,flipy,sx,sy,clip,transparency,transparent_color,1);
  2053. }
  2054.  
  2055.  
  2056. /***************************************************************************
  2057.  
  2058.   Use drawgfx() to copy a bitmap onto another at the given position.
  2059.   This function will very likely change in the future.
  2060.  
  2061. ***************************************************************************/
  2062. void copybitmap(struct osd_bitmap *dest,struct osd_bitmap *src,int flipx,int flipy,int sx,int sy,
  2063.         const struct rectangle *clip,int transparency,int transparent_color)
  2064. {
  2065.     static struct GfxElement mygfx =
  2066.     {
  2067.         0,0,0,    /* filled in later */
  2068.         1,1,0,1
  2069.     };
  2070.  
  2071.     mygfx.width = src->width;
  2072.     mygfx.height = src->height;
  2073.     mygfx.gfxdata = src;
  2074.  
  2075.     /* ASG 980209 -- separate 8-bit from 16-bit here */
  2076.     if (dest->depth != 16)
  2077.         drawgfx_core8(dest,&mygfx,0,0,flipx,flipy,sx,sy,clip,transparency,transparent_color,0);    /* ASG 971011 */
  2078.     else
  2079.         drawgfx_core16(dest,&mygfx,0,0,flipx,flipy,sx,sy,clip,transparency,transparent_color,0);    /* ASG 971011 */
  2080. }
  2081.  
  2082.  
  2083. void copybitmapzoom(struct osd_bitmap *dest,struct osd_bitmap *src,int flipx,int flipy,int sx,int sy,
  2084.         const struct rectangle *clip,int transparency,int transparent_color,int scalex,int scaley)
  2085. {
  2086.     static struct GfxElement mygfx =
  2087.     {
  2088.         0,0,0,    /* filled in later */
  2089.         1,1,0,1
  2090.     };
  2091. unsigned short hacktable[256];
  2092. int i;
  2093.  
  2094.     mygfx.width = src->width;
  2095.     mygfx.height = src->height;
  2096.     mygfx.gfxdata = src;
  2097. mygfx.colortable = hacktable;
  2098. for (i = 0;i < 256;i++) hacktable[i] = i;
  2099.     drawgfxzoom(dest,&mygfx,0,0,flipx,flipy,sx,sy,clip,transparency,transparent_color,scalex,scaley);    /* ASG 971011 */
  2100. }
  2101.  
  2102.  
  2103. /***************************************************************************
  2104.  
  2105.   Copy a bitmap onto another with scroll and wraparound.
  2106.   This function supports multiple independently scrolling rows/columns.
  2107.   "rows" is the number of indepentently scrolling rows. "rowscroll" is an
  2108.   array of integers telling how much to scroll each row. Same thing for
  2109.   "cols" and "colscroll".
  2110.   If the bitmap cannot scroll in one direction, set rows or columns to 0.
  2111.   If the bitmap scrolls as a whole, set rows and/or cols to 1.
  2112.   Bidirectional scrolling is, of course, supported only if the bitmap
  2113.   scrolls as a whole in at least one direction.
  2114.  
  2115. ***************************************************************************/
  2116. void copyscrollbitmap(struct osd_bitmap *dest,struct osd_bitmap *src,
  2117.         int rows,const int *rowscroll,int cols,const int *colscroll,
  2118.         const struct rectangle *clip,int transparency,int transparent_color)
  2119. {
  2120.     int srcwidth,srcheight;
  2121.  
  2122.  
  2123.     if (rows == 0 && cols == 0)
  2124.     {
  2125.         copybitmap(dest,src,0,0,0,0,clip,transparency,transparent_color);
  2126.         return;
  2127.     }
  2128.  
  2129.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  2130.     {
  2131.         srcwidth = src->height;
  2132.         srcheight = src->width;
  2133.     }
  2134.     else
  2135.     {
  2136.         srcwidth = src->width;
  2137.         srcheight = src->height;
  2138.     }
  2139.  
  2140.     if (rows == 0)
  2141.     {
  2142.         /* scrolling columns */
  2143.         int col,colwidth;
  2144.         struct rectangle myclip;
  2145.  
  2146.  
  2147.         colwidth = srcwidth / cols;
  2148.  
  2149.         myclip.min_y = clip->min_y;
  2150.         myclip.max_y = clip->max_y;
  2151.  
  2152.         col = 0;
  2153.         while (col < cols)
  2154.         {
  2155.             int cons,scroll;
  2156.  
  2157.  
  2158.             /* count consecutive columns scrolled by the same amount */
  2159.             scroll = colscroll[col];
  2160.             cons = 1;
  2161.             while (col + cons < cols &&    colscroll[col + cons] == scroll)
  2162.                 cons++;
  2163.  
  2164.             if (scroll < 0) scroll = srcheight - (-scroll) % srcheight;
  2165.             else scroll %= srcheight;
  2166.  
  2167.             myclip.min_x = col * colwidth;
  2168.             if (myclip.min_x < clip->min_x) myclip.min_x = clip->min_x;
  2169.             myclip.max_x = (col + cons) * colwidth - 1;
  2170.             if (myclip.max_x > clip->max_x) myclip.max_x = clip->max_x;
  2171.  
  2172.             copybitmap(dest,src,0,0,0,scroll,&myclip,transparency,transparent_color);
  2173.             copybitmap(dest,src,0,0,0,scroll - srcheight,&myclip,transparency,transparent_color);
  2174.  
  2175.             col += cons;
  2176.         }
  2177.     }
  2178.     else if (cols == 0)
  2179.     {
  2180.         /* scrolling rows */
  2181.         int row,rowheight;
  2182.         struct rectangle myclip;
  2183.  
  2184.  
  2185.         rowheight = srcheight / rows;
  2186.  
  2187.         myclip.min_x = clip->min_x;
  2188.         myclip.max_x = clip->max_x;
  2189.  
  2190.         row = 0;
  2191.         while (row < rows)
  2192.         {
  2193.             int cons,scroll;
  2194.  
  2195.  
  2196.             /* count consecutive rows scrolled by the same amount */
  2197.             scroll = rowscroll[row];
  2198.             cons = 1;
  2199.             while (row + cons < rows &&    rowscroll[row + cons] == scroll)
  2200.                 cons++;
  2201.  
  2202.             if (scroll < 0) scroll = srcwidth - (-scroll) % srcwidth;
  2203.             else scroll %= srcwidth;
  2204.  
  2205.             myclip.min_y = row * rowheight;
  2206.             if (myclip.min_y < clip->min_y) myclip.min_y = clip->min_y;
  2207.             myclip.max_y = (row + cons) * rowheight - 1;
  2208.             if (myclip.max_y > clip->max_y) myclip.max_y = clip->max_y;
  2209.  
  2210.             copybitmap(dest,src,0,0,scroll,0,&myclip,transparency,transparent_color);
  2211.             copybitmap(dest,src,0,0,scroll - srcwidth,0,&myclip,transparency,transparent_color);
  2212.  
  2213.             row += cons;
  2214.         }
  2215.     }
  2216.     else if (rows == 1 && cols == 1)
  2217.     {
  2218.         /* XY scrolling playfield */
  2219.         int scrollx,scrolly;
  2220.  
  2221.  
  2222.         if (rowscroll[0] < 0) scrollx = srcwidth - (-rowscroll[0]) % srcwidth;
  2223.         else scrollx = rowscroll[0] % srcwidth;
  2224.  
  2225.         if (colscroll[0] < 0) scrolly = srcheight - (-colscroll[0]) % srcheight;
  2226.         else scrolly = colscroll[0] % srcheight;
  2227.  
  2228.         copybitmap(dest,src,0,0,scrollx,scrolly,clip,transparency,transparent_color);
  2229.         copybitmap(dest,src,0,0,scrollx,scrolly - srcheight,clip,transparency,transparent_color);
  2230.         copybitmap(dest,src,0,0,scrollx - srcwidth,scrolly,clip,transparency,transparent_color);
  2231.         copybitmap(dest,src,0,0,scrollx - srcwidth,scrolly - srcheight,clip,transparency,transparent_color);
  2232.     }
  2233.     else if (rows == 1)
  2234.     {
  2235.         /* scrolling columns + horizontal scroll */
  2236.         int col,colwidth;
  2237.         int scrollx;
  2238.         struct rectangle myclip;
  2239.  
  2240.  
  2241.         if (rowscroll[0] < 0) scrollx = srcwidth - (-rowscroll[0]) % srcwidth;
  2242.         else scrollx = rowscroll[0] % srcwidth;
  2243.  
  2244.         colwidth = srcwidth / cols;
  2245.  
  2246.         myclip.min_y = clip->min_y;
  2247.         myclip.max_y = clip->max_y;
  2248.  
  2249.         col = 0;
  2250.         while (col < cols)
  2251.         {
  2252.             int cons,scroll;
  2253.  
  2254.  
  2255.             /* count consecutive columns scrolled by the same amount */
  2256.             scroll = colscroll[col];
  2257.             cons = 1;
  2258.             while (col + cons < cols &&    colscroll[col + cons] == scroll)
  2259.                 cons++;
  2260.  
  2261.             if (scroll < 0) scroll = srcheight - (-scroll) % srcheight;
  2262.             else scroll %= srcheight;
  2263.  
  2264.             myclip.min_x = col * colwidth + scrollx;
  2265.             if (myclip.min_x < clip->min_x) myclip.min_x = clip->min_x;
  2266.             myclip.max_x = (col + cons) * colwidth - 1 + scrollx;
  2267.             if (myclip.max_x > clip->max_x) myclip.max_x = clip->max_x;
  2268.  
  2269.             copybitmap(dest,src,0,0,scrollx,scroll,&myclip,transparency,transparent_color);
  2270.             copybitmap(dest,src,0,0,scrollx,scroll - srcheight,&myclip,transparency,transparent_color);
  2271.  
  2272.             myclip.min_x = col * colwidth + scrollx - srcwidth;
  2273.             if (myclip.min_x < clip->min_x) myclip.min_x = clip->min_x;
  2274.             myclip.max_x = (col + cons) * colwidth - 1 + scrollx - srcwidth;
  2275.             if (myclip.max_x > clip->max_x) myclip.max_x = clip->max_x;
  2276.  
  2277.             copybitmap(dest,src,0,0,scrollx - srcwidth,scroll,&myclip,transparency,transparent_color);
  2278.             copybitmap(dest,src,0,0,scrollx - srcwidth,scroll - srcheight,&myclip,transparency,transparent_color);
  2279.  
  2280.             col += cons;
  2281.         }
  2282.     }
  2283.     else if (cols == 1)
  2284.     {
  2285.         /* scrolling rows + vertical scroll */
  2286.         int row,rowheight;
  2287.         int scrolly;
  2288.         struct rectangle myclip;
  2289.  
  2290.  
  2291.         if (colscroll[0] < 0) scrolly = srcheight - (-colscroll[0]) % srcheight;
  2292.         else scrolly = colscroll[0] % srcheight;
  2293.  
  2294.         rowheight = srcheight / rows;
  2295.  
  2296.         myclip.min_x = clip->min_x;
  2297.         myclip.max_x = clip->max_x;
  2298.  
  2299.         row = 0;
  2300.         while (row < rows)
  2301.         {
  2302.             int cons,scroll;
  2303.  
  2304.  
  2305.             /* count consecutive rows scrolled by the same amount */
  2306.             scroll = rowscroll[row];
  2307.             cons = 1;
  2308.             while (row + cons < rows &&    rowscroll[row + cons] == scroll)
  2309.                 cons++;
  2310.  
  2311.             if (scroll < 0) scroll = srcwidth - (-scroll) % srcwidth;
  2312.             else scroll %= srcwidth;
  2313.  
  2314.             myclip.min_y = row * rowheight + scrolly;
  2315.             if (myclip.min_y < clip->min_y) myclip.min_y = clip->min_y;
  2316.             myclip.max_y = (row + cons) * rowheight - 1 + scrolly;
  2317.             if (myclip.max_y > clip->max_y) myclip.max_y = clip->max_y;
  2318.  
  2319.             copybitmap(dest,src,0,0,scroll,scrolly,&myclip,transparency,transparent_color);
  2320.             copybitmap(dest,src,0,0,scroll - srcwidth,scrolly,&myclip,transparency,transparent_color);
  2321.  
  2322.             myclip.min_y = row * rowheight + scrolly - srcheight;
  2323.             if (myclip.min_y < clip->min_y) myclip.min_y = clip->min_y;
  2324.             myclip.max_y = (row + cons) * rowheight - 1 + scrolly - srcheight;
  2325.             if (myclip.max_y > clip->max_y) myclip.max_y = clip->max_y;
  2326.  
  2327.             copybitmap(dest,src,0,0,scroll,scrolly - srcheight,&myclip,transparency,transparent_color);
  2328.             copybitmap(dest,src,0,0,scroll - srcwidth,scrolly - srcheight,&myclip,transparency,transparent_color);
  2329.  
  2330.             row += cons;
  2331.         }
  2332.     }
  2333. }
  2334.  
  2335.  
  2336. /* fill a bitmap using the specified pen */
  2337. void fillbitmap(struct osd_bitmap *dest,int pen,const struct rectangle *clip)
  2338. {
  2339.     int sx,sy,ex,ey,y;
  2340.     struct rectangle myclip;
  2341.  
  2342.  
  2343.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  2344.     {
  2345.         if (clip)
  2346.         {
  2347.             myclip.min_x = clip->min_y;
  2348.             myclip.max_x = clip->max_y;
  2349.             myclip.min_y = clip->min_x;
  2350.             myclip.max_y = clip->max_x;
  2351.             clip = &myclip;
  2352.         }
  2353.     }
  2354.     if (Machine->orientation & ORIENTATION_FLIP_X)
  2355.     {
  2356.         if (clip)
  2357.         {
  2358.             int temp;
  2359.  
  2360.  
  2361.             temp = clip->min_x;
  2362.             myclip.min_x = dest->width-1 - clip->max_x;
  2363.             myclip.max_x = dest->width-1 - temp;
  2364.             myclip.min_y = clip->min_y;
  2365.             myclip.max_y = clip->max_y;
  2366.             clip = &myclip;
  2367.         }
  2368.     }
  2369.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  2370.     {
  2371.         if (clip)
  2372.         {
  2373.             int temp;
  2374.  
  2375.  
  2376.             myclip.min_x = clip->min_x;
  2377.             myclip.max_x = clip->max_x;
  2378.             temp = clip->min_y;
  2379.             myclip.min_y = dest->height-1 - clip->max_y;
  2380.             myclip.max_y = dest->height-1 - temp;
  2381.             clip = &myclip;
  2382.         }
  2383.     }
  2384.  
  2385.  
  2386.     sx = 0;
  2387.     ex = dest->width - 1;
  2388.     sy = 0;
  2389.     ey = dest->height - 1;
  2390.  
  2391.     if (clip && sx < clip->min_x) sx = clip->min_x;
  2392.     if (clip && ex > clip->max_x) ex = clip->max_x;
  2393.     if (sx > ex) return;
  2394.     if (clip && sy < clip->min_y) sy = clip->min_y;
  2395.     if (clip && ey > clip->max_y) ey = clip->max_y;
  2396.     if (sy > ey) return;
  2397.  
  2398.     osd_mark_dirty (sx,sy,ex,ey,0);    /* ASG 971011 */
  2399.  
  2400.     /* ASG 980211 */
  2401.     if (dest->depth == 16)
  2402.     {
  2403.         if ((pen >> 8) == (pen & 0xff))
  2404.         {
  2405.             for (y = sy;y <= ey;y++)
  2406.                 memset(&dest->line[y][sx*2],pen&0xff,(ex-sx+1)*2);
  2407.         }
  2408.         else
  2409.         {
  2410.             for (y = sy;y <= ey;y++)
  2411.             {
  2412.                 unsigned short *p = (unsigned short *)&dest->line[y][sx*2];
  2413.                 int x;
  2414.                 for (x = sx;x <= ex;x++)
  2415.                     *p++ = pen;
  2416.             }
  2417.         }
  2418.     }
  2419.     else
  2420.     {
  2421.         for (y = sy;y <= ey;y++)
  2422.             memset(&dest->line[y][sx],pen,ex-sx+1);
  2423.     }
  2424. }
  2425.  
  2426.  
  2427. void drawgfxzoom( struct osd_bitmap *dest_bmp,const struct GfxElement *gfx,
  2428.         unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy,
  2429.         const struct rectangle *clip,int transparency,int transparent_color,int scalex, int scaley)
  2430. {
  2431.     struct rectangle myclip;
  2432.  
  2433.  
  2434.     /* only support TRANSPARENCY_PEN and TRANSPARENCY_COLOR */
  2435.     if (transparency != TRANSPARENCY_PEN && transparency != TRANSPARENCY_COLOR)
  2436.         return;
  2437.  
  2438.     if (transparency == TRANSPARENCY_COLOR)
  2439.         transparent_color = Machine->pens[transparent_color];
  2440.  
  2441.  
  2442.     /*
  2443.     scalex and scaley are 16.16 fixed point numbers
  2444.     1<<15 : shrink to 50%
  2445.     1<<16 : uniform scale
  2446.     1<<17 : double to 200%
  2447.     */
  2448.  
  2449.  
  2450.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  2451.     {
  2452.         int temp;
  2453.  
  2454.         temp = sx;
  2455.         sx = sy;
  2456.         sy = temp;
  2457.  
  2458.         temp = flipx;
  2459.         flipx = flipy;
  2460.         flipy = temp;
  2461.  
  2462.         temp = scalex;
  2463.         scalex = scaley;
  2464.         scaley = temp;
  2465.  
  2466.         if (clip)
  2467.         {
  2468.             /* clip and myclip might be the same, so we need a temporary storage */
  2469.             temp = clip->min_x;
  2470.             myclip.min_x = clip->min_y;
  2471.             myclip.min_y = temp;
  2472.             temp = clip->max_x;
  2473.             myclip.max_x = clip->max_y;
  2474.             myclip.max_y = temp;
  2475.             clip = &myclip;
  2476.         }
  2477.     }
  2478.     if (Machine->orientation & ORIENTATION_FLIP_X)
  2479.     {
  2480.         sx = dest_bmp->width - ((gfx->width * scalex + 0x7fff) >> 16) - sx;
  2481.         if (clip)
  2482.         {
  2483.             int temp;
  2484.  
  2485.  
  2486.             /* clip and myclip might be the same, so we need a temporary storage */
  2487.             temp = clip->min_x;
  2488.             myclip.min_x = dest_bmp->width-1 - clip->max_x;
  2489.             myclip.max_x = dest_bmp->width-1 - temp;
  2490.             myclip.min_y = clip->min_y;
  2491.             myclip.max_y = clip->max_y;
  2492.             clip = &myclip;
  2493.         }
  2494.     }
  2495.     if (Machine->orientation & ORIENTATION_FLIP_Y)
  2496.     {
  2497.         sy = dest_bmp->height - ((gfx->height * scaley + 0x7fff) >> 16) - sy;
  2498.         if (clip)
  2499.         {
  2500.             int temp;
  2501.  
  2502.  
  2503.             myclip.min_x = clip->min_x;
  2504.             myclip.max_x = clip->max_x;
  2505.             /* clip and myclip might be the same, so we need a temporary storage */
  2506.             temp = clip->min_y;
  2507.             myclip.min_y = dest_bmp->height-1 - clip->max_y;
  2508.             myclip.max_y = dest_bmp->height-1 - temp;
  2509.             clip = &myclip;
  2510.         }
  2511.     }
  2512.  
  2513.  
  2514.     /* ASG 980209 -- added 16-bit version */
  2515.     if (dest_bmp->depth != 16)
  2516.     {
  2517.         if( gfx && gfx->colortable )
  2518.         {
  2519.             const unsigned short *pal = &gfx->colortable[gfx->color_granularity * (color % gfx->total_colors)]; /* ASG 980209 */
  2520.             struct osd_bitmap *source_bmp = gfx->gfxdata;
  2521.             int source_base = (code % gfx->total_elements) * gfx->height;
  2522.  
  2523.             int sprite_screen_height = (scaley*gfx->height+0x7fff)>>16;
  2524.             int sprite_screen_width = (scalex*gfx->width+0x7fff)>>16;
  2525.  
  2526.             /* compute sprite increment per screen pixel */
  2527.             int dx = (gfx->width<<16)/sprite_screen_width;
  2528.             int dy = (gfx->height<<16)/sprite_screen_height;
  2529.  
  2530.             int ex = sx+sprite_screen_width;
  2531.             int ey = sy+sprite_screen_height;
  2532.  
  2533.             int x_index_base;
  2534.             int y_index;
  2535.  
  2536.             if( flipx )
  2537.             {
  2538.                 x_index_base = (sprite_screen_width-1)*dx;
  2539.                 dx = -dx;
  2540.             }
  2541.             else
  2542.             {
  2543.                 x_index_base = 0;
  2544.             }
  2545.  
  2546.             if( flipy )
  2547.             {
  2548.                 y_index = (sprite_screen_height-1)*dy;
  2549.                 dy = -dy;
  2550.             }
  2551.             else
  2552.             {
  2553.                 y_index = 0;
  2554.             }
  2555.  
  2556.             if( clip )
  2557.             {
  2558.                 if( sx < clip->min_x)
  2559.                 { /* clip left */
  2560.                     int pixels = clip->min_x-sx;
  2561.                     sx += pixels;
  2562.                     x_index_base += pixels*dx;
  2563.                 }
  2564.                 if( sy < clip->min_y )
  2565.                 { /* clip top */
  2566.                     int pixels = clip->min_y-sy;
  2567.                     sy += pixels;
  2568.                     y_index += pixels*dy;
  2569.                 }
  2570.                 /* NS 980211 - fixed incorrect clipping */
  2571.                 if( ex > clip->max_x+1 )
  2572.                 { /* clip right */
  2573.                     int pixels = ex-clip->max_x-1;
  2574.                     ex -= pixels;
  2575.                 }
  2576.                 if( ey > clip->max_y+1 )
  2577.                 { /* clip bottom */
  2578.                     int pixels = ey-clip->max_y-1;
  2579.                     ey -= pixels;
  2580.                 }
  2581.             }
  2582.  
  2583.             if( ex>sx )
  2584.             { /* skip if inner loop doesn't draw anything */
  2585.                 int y;
  2586.  
  2587.                 /* case 1: TRANSPARENCY_PEN */
  2588.                 if (transparency == TRANSPARENCY_PEN)
  2589.                 {
  2590.                     for( y=sy; y<ey; y++ )
  2591.                     {
  2592.                         unsigned char *source = source_bmp->line[source_base+(y_index>>16)];
  2593.                         unsigned char *dest = dest_bmp->line[y];
  2594.  
  2595.                         int x, x_index = x_index_base;
  2596.                         for( x=sx; x<ex; x++ )
  2597.                         {
  2598.                             int c = source[x_index>>16];
  2599.                             if( c != transparent_color ) dest[x] = pal[c];
  2600.                             x_index += dx;
  2601.                         }
  2602.  
  2603.                         y_index += dy;
  2604.                     }
  2605.                 }
  2606.  
  2607.                 /* case 2: TRANSPARENCY_COLOR */
  2608.                 else if (transparency == TRANSPARENCY_COLOR)
  2609.                 {
  2610.                     for( y=sy; y<ey; y++ )
  2611.                     {
  2612.                         unsigned char *source = source_bmp->line[source_base+(y_index>>16)];
  2613.                         unsigned char *dest = dest_bmp->line[y];
  2614.  
  2615.                         int x, x_index = x_index_base;
  2616.                         for( x=sx; x<ex; x++ )
  2617.                         {
  2618.                             int c = pal[source[x_index>>16]];
  2619.                             if( c != transparent_color ) dest[x] = c;
  2620.                             x_index += dx;
  2621.                         }
  2622.  
  2623.                         y_index += dy;
  2624.                     }
  2625.                 }
  2626.             }
  2627.  
  2628.         }
  2629.     }
  2630.  
  2631.     /* ASG 980209 -- new 16-bit part */
  2632.     else
  2633.     {
  2634.         if( gfx && gfx->colortable )
  2635.         {
  2636.             const unsigned short *pal = &gfx->colortable[gfx->color_granularity * (color % gfx->total_colors)]; /* ASG 980209 */
  2637.             struct osd_bitmap *source_bmp = gfx->gfxdata;
  2638.             int source_base = (code % gfx->total_elements) * gfx->height;
  2639.  
  2640.             int sprite_screen_height = (scaley*gfx->height+0x7fff)>>16;
  2641.             int sprite_screen_width = (scalex*gfx->width+0x7fff)>>16;
  2642.  
  2643.             /* compute sprite increment per screen pixel */
  2644.             int dx = (gfx->width<<16)/sprite_screen_width;
  2645.             int dy = (gfx->height<<16)/sprite_screen_height;
  2646.  
  2647.             int ex = sx+sprite_screen_width;
  2648.             int ey = sy+sprite_screen_height;
  2649.  
  2650.             int x_index_base;
  2651.             int y_index;
  2652.  
  2653.             if( flipx )
  2654.             {
  2655.                 x_index_base = (sprite_screen_width-1)*dx;
  2656.                 dx = -dx;
  2657.             }
  2658.             else
  2659.             {
  2660.                 x_index_base = 0;
  2661.             }
  2662.  
  2663.             if( flipy )
  2664.             {
  2665.                 y_index = (sprite_screen_height-1)*dy;
  2666.                 dy = -dy;
  2667.             }
  2668.             else
  2669.             {
  2670.                 y_index = 0;
  2671.             }
  2672.  
  2673.             if( clip )
  2674.             {
  2675.                 if( sx < clip->min_x)
  2676.                 { /* clip left */
  2677.                     int pixels = clip->min_x-sx;
  2678.                     sx += pixels;
  2679.                     x_index_base += pixels*dx;
  2680.                 }
  2681.                 if( sy < clip->min_y )
  2682.                 { /* clip top */
  2683.                     int pixels = clip->min_y-sy;
  2684.                     sy += pixels;
  2685.                     y_index += pixels*dy;
  2686.                 }
  2687.                 /* NS 980211 - fixed incorrect clipping */
  2688.                 if( ex > clip->max_x+1 )
  2689.                 { /* clip right */
  2690.                     int pixels = ex-clip->max_x-1;
  2691.                     ex -= pixels;
  2692.                 }
  2693.                 if( ey > clip->max_y+1 )
  2694.                 { /* clip bottom */
  2695.                     int pixels = ey-clip->max_y-1;
  2696.                     ey -= pixels;
  2697.                 }
  2698.             }
  2699.  
  2700.             if( ex>sx )
  2701.             { /* skip if inner loop doesn't draw anything */
  2702.                 int y;
  2703.  
  2704.                 /* case 1: TRANSPARENCY_PEN */
  2705.                 if (transparency == TRANSPARENCY_PEN)
  2706.                 {
  2707.                     for( y=sy; y<ey; y++ )
  2708.                     {
  2709.                         unsigned char *source = source_bmp->line[source_base+(y_index>>16)];
  2710.                         unsigned short *dest = (unsigned short *)dest_bmp->line[y];
  2711.  
  2712.                         int x, x_index = x_index_base;
  2713.                         for( x=sx; x<ex; x++ )
  2714.                         {
  2715.                             int c = source[x_index>>16];
  2716.                             if( c != transparent_color ) dest[x] = pal[c];
  2717.                             x_index += dx;
  2718.                         }
  2719.  
  2720.                         y_index += dy;
  2721.                     }
  2722.                 }
  2723.  
  2724.                 /* case 2: TRANSPARENCY_COLOR */
  2725.                 else if (transparency == TRANSPARENCY_COLOR)
  2726.                 {
  2727.                     for( y=sy; y<ey; y++ )
  2728.                     {
  2729.                         unsigned char *source = source_bmp->line[source_base+(y_index>>16)];
  2730.                         unsigned short *dest = (unsigned short *)dest_bmp->line[y];
  2731.  
  2732.                         int x, x_index = x_index_base;
  2733.                         for( x=sx; x<ex; x++ )
  2734.                         {
  2735.                             int c = pal[source[x_index>>16]];
  2736.                             if( c != transparent_color ) dest[x] = c;
  2737.                             x_index += dx;
  2738.                         }
  2739.  
  2740.                         y_index += dy;
  2741.                     }
  2742.                 }
  2743.             }
  2744.         }
  2745.     }
  2746. }
  2747.